データにまつわるトラブル事例(2)〜産業用システム編〜
前回はリレーショナルデータベースを使った情報システムでよくあるトラブルについて書きました。今回は、これとはかなり毛色の違う、産業用システムでよくあるトラブルについて書きます。
産業用システムにも色々ありますが、ここでは、製造業のFAシステムや電力・ガス・水道などのインフラ提供事業者に使われる監視制御システムなどを取り上げます。これらには、普通の情報系システムとは少し違う以下の特徴があります。
データの入出力先が「モノ」 業務系情報システムのデータの入出力先が端末等を介した「人」が中心なのに対し、産業用のシステムではセンサーやアクチュエーターやコントローラーなどの「モノ」も入出力先になります。センサーなどで一定周期で収集されるデータや不定期にイベント的に発生するアラームなどのデータを取り扱います。
安定稼働・連続稼働 いわゆる「ミッションクリティカル」なシステムであり、停止することなく連続的に安定稼働することが重要になります。24時間365日稼働が基本で、システムを停止できるのは非常に限られた期間のみ(例えば、年1回数時間など)です。システム障害が起きた場合でも連続して稼働ができるように機器・サーバなどは冗長化され、複数設置されます。
このようなシステムの問題について書かれているものはあまり見かけませんが、今回は私が経験したことのあるトラブル事例をいくつか挙げてみます。
1. 予期せぬシステムの停止
症状
システムを運用し始めて、一定期間経つと止まってしまう問題です。システム内部に蓄積されるデータのサイズがどんどん増加していって、ソフトウェアで使用可能なディスク容量や、メモリ容量の上限を超えてしまうことにより起きます。ディスクやメモリを使ってしまったソフトウェアだけでなく、システム全体が動かなくなります。安定稼働・連続稼働が重要な産業用システムでは許容できない問題であり、大きなトラブルになりがちです。
原因
よくあるのは、センサーなどから送られてくるデータの蓄積方法に問題がある場合です。センサーからのデータは通常定周期で継続的に送られてきますので、受取るデータは時間と比例して増えていきます。これをどんどんシステム内に蓄積していると、当然いつかディスクやメモリの容量を食い潰してしまいます。過去のデータは捨てることが必要です。
リレーショナルデータベースを使う場合、過去のデータを消去しても、データベースが使うメモリやファイルのサイズは減らずにどんどん増えていくということがあります。データベースが確保しているメモリやファイルの中に使っていない空き領域が多数発生し、データの断片化が起きるからです。(データの断片化については、前回のブログの「3. 性能が出ない」にも書いていますので参照してみてください。)
また意外と見落としがちなのが、アプリケーションソフトウェアから出力されるログファイルで、システムを長時間連続稼働をしていると、これが肥大化しディスクを圧迫するケースもよく見られます。(ログも広い範囲でのデータの一種です)
防止策
問題が発生したときによくやる、手っ取り早い対処方法は、データがシステム容量を食い潰すまでの時間を延ばすために、メモリやディスク増設することです。ただ、これは根本的な問題の解決にはなっていません。いつかは問題が起きます。将来設備増強などにより、監視制御対象が大幅に増えた場合、センサーからくるデータも増え、また容量が足りなくなるかもしれません。
この問題に対処するために、産業用システムでは、データサイズが一定値以上増加しない蓄積方法をとるのが「定石」とされています。よくあるのは、循環型のデータ構造を独自に実装する方法です。データの挿入や削除をせず古いデータは上書きすることで、データサイズを一定に保つことができます。この方式だと、データの挿入や削除をしませんので、データの断片化が起きることはありません。
アプリケーションログファイルのサイズ増加対策としては、過去のログを削除していく、ログローテーションがあります。よく知られた一般的な方法であり、ほとんどの場合これが使われます。自分たちでアプリケーションソフトを開発する場合はこれで問題ないのですが、注意しないといけないのがOSSなを組み込んで使っている場合です。OSSのログがどのように出力されるかチェックしておくことも必要です。
また、当たり前ではありますが、事前にデータ量を見積もっておくことも大事です。システム設計時点で、一日にどれくらいの量のデータが蓄積されるかを予測し、それに合わせたソフトウェアの実装やシステムの運用を計画すべきです。
2. 一時的に動かなくなることがある
症状
工場やプラントの状態を監視システムなど一定の時間間隔で状態を更新表示するようなシステムで、一時的に画面が更新されないなど、一時的に動作が停止しているように見える場合があります。
これは、バースト的なデータの発生によりシステムのどこかがボトルネックになり、データが流れないことにより全体が停止しているように見えるケースがほとんどです。データの処理が終われば、元に戻りますが、安定した動作を保証する必要のある産業用システムではこれも、許容されない問題です。
原因
一般的な情報システムでは、リレーショナルデータベースを中心とした「ハブ&スポーク型」のアーキテクチャがよく用いられるのに対し、監視制御システムでは、ある程度のリアルタイム性が必要なため、非同期な「イベント駆動型(メッセージ駆動型)」のアーキテクチャが用いられます。このアーキテクチャでは、データは「イベント」として扱われ、ソフトウェアの処理プロセス間でやり取りされます。データが渡された処理プロセスで処理を行い、その結果を別のイベントとして他の処理プロセスに受け渡します。
工場やプラントなどの監視制御システムには、センサーの計測データなどが定常的に一定の時間間隔ごとに送られてくる他、監視制御対象に何らかの状態の変化が起きた時にそれを通知するデータが不定期に送られてきます。あるいは、センサーデータの値が閾値を超えたかどうかを判断してシステムの内部でデータを発生させることもあります。
各処理プロセスがイベントを受け取った後、次のイベントを受け取るまでに処理が完了できれば、問題はないのですが、処理に時間がかかるプロセスがあり、ここに多くのイベントが集中してしまうと、このプロセスがボトルネックとなりイベントデータの流れが滞ってしまい、処理が止まったように見えます。例えば、監視対象が一斉に状態変化を起こして、通知データが大量に送られくる場合にこの様なことが起こりえます。
防止策
システム設計段階で、プロセス間の「データフロー」を意識した設計をすることが重要になります。どの程度のデータがどういうタイミングで発生するかを予測し、それを基に、一つのプロセスにイベントの流れが集中したり、処理量が偏ったりすることがないように設計することが必要です。
また、重大なトラブルとならないようにするために、開発プロセスの早い段階で問題を発見することも重要です。システムテストフェーズで、どれくらいのデータフローがあるかを把握するとともに、各プロセスのCPU使用率も監視しておきます。実際に大量のイベントをバースト的に発生させて負荷の計測を行い、CPU負荷が100%近くなってしまうプロセスがないかどうかチェックします。また、定常状態で各処理プロセスCPU使用率が偏りなく低く抑えられているかも確認し、バースト的なイベントが発生した時のための余裕がどれだけあるかもチェックしておきます。
4. システムの起動・停止にやたらと時間がかかる
現象
取り上げられることは少ないのですが、システムの起動・停止時間の話は、システムの運用に重大な影響があり、かつ解決するのがなかなか難しい問題です。
システムの運用上、保守や更新のためにシステムを停止・起動しなければならないことが必ずあります。システムの停止できるのは、大抵の場合、運用に影響の出ない夜間の数時間などに限られます。限られた時間で、データのバックアップ、ソフトウェアの投入、設定の変更、動作試験などを完了させなければなりません。
しかし、システムの停止・起動に時間がかかってしまうと、実質的に作業ができる時間がさらに短くなってしまいます。システムの規模が大きいと、停止、起動に数十分の時間がかかるものはザラにありますし、1時間以上かかっているものも見かけます。こうなってしまうと、動作試験をしている最中に間違いが見つかっても、これを修正して再起動をかけるということが非常に難しくなります。
原因
起動・停止時間のうち、大きな割合を占めているのは、ファイルシステムへのデータの書込みや読込みの時間です。データの量が大きくなると、この時間が非常に大きくなってしまいます。
システム停止時
産業用システムの場合、リアルタイム性を確保のためにシステムの運用中は、データをハードディスクなどのストレージに保存せず、メモリ上で全て処理する様なシステムがあります。メモリ上のデータはシステムを停止し、電源を落としてしまうと消えて無くなってしまうので、次に起動した後もデータを使うために、停止前にメモリ上のデータの状態(スナップショット)をまとめてストレージに書き出します。データ量が多いとこの処理に時間がかかってしまいます。
システム起動時
システム停止時に取得したスナップショットをディスクなどのストレージから読み込み、メモリ上のデータ構造に再構築する処理が行われます。読み出すデータが多いとこれにも時間がかかります。
さらに、システム障害対策として、アクティブスタンバイ型の冗長系を持つシステムの場合、複数のサーバ(主系、従系)は常に同じ状態を保持し続けることが必要になります。このため起動時に、主系から従系にデータを送り、ミラーリングする処理が行われ、ここでまた時間がかかります。
防止策
システム起動・停止時間の短縮に一番効果があるのは、ストレージへの書込み・読出しをできるだけ少なくすることです。特にストレージへの書き込みは、読み込みより圧倒的に大きな時間がかかりますので、データ書き込みが多いシステム停止時の時間の短縮に大きな効果が期待できます。スナップショットとしてストレージに書き出すデータ項目を精査し、できるだけ少なくしていきます。保持しているデータの全てを書き出す必要はないはずで、本当に再起動後に必要なものに絞り込んだり、前回の書き出しからの差分だけを書き出すなどにより、書き出すスナップショットをできるだけ小さくしてファイルアクセス時間の短縮を図ります。
データの読出しの時間には、ファイルI/Oにかかっている時間以外に、ファイルに書かれている内容を解釈し、メモリ上のデータ構造に変換する処理にかかる時間が含まれます。この変換処理を「パース(Parse)」と呼び、変換を行うソフトウェアのことを「パーサー(Parser)」と呼びます。最近では、ファイルに保存されるフォーマットに、複雑なデータ構造を記述しやすいテキスト形式のJSONやXMLが使われることが多くなっていますが、パース処理には結構時間がかかります。JSONやXMLのパーサはライブラリ化され、色々な種類のものが使える用になっています。中には、機能を削って高速化を図っているしたものもありますので、これを利用することで時間を短縮することができます。
(続く)