監視制御を行うWebアプリケーションの基本構造
変電所や高速道路、気象レーダーなどの社会のインフラを担うシステムから、家庭で使われる照明、空調といった機器など、監視制御が必要とされるシステムや機器は数多く存在します。従来、これらに対する監視制御は限られた場所からのみ使用可能でした。しかし、利便性を高めるためには現場作業員が外部から使用するだけでなく、集中豪雨や地震のなどの異常事態が発生した際、一般の方でも利用できるようにする必要があります。自由にどこからでも、どの端末からでも利用できることが求められているのです。この要望に応えるため、監視制御システムの一部またはその多くをWebアプリケーションとして実装するケースが増えています。
監視制御システムとしてのWebアプリケーションは、従来のWebサイトやWebアプリケーションとは異なる動作が求められる場合があります。例えば、警告が発生するなどサーバー側での状態変化を一定時間内に表示可能にする必要があるなど、より動的な振る舞いが求められます。このため画面遷移を基本としたWebサイトとは異なり、WebSocketやLong pollingといった双方向通信や、Ajaxを用いた動的更新を多用したSPA(Single-Page Application)型と呼ばれるWebアプリケーションとして作成されます。それに加え、一時的通信切断やサーバー停止後に、自動的に正常な状態に復帰するような安定性も求められます。これらの要求を安定して実現するために、現在何を表示しているのかといったブラウザの状態をサーバー側にも持たせます。そしてブラウザとサーバーが持つこれらの状態を、WebSocketやLong pollingを使用して同期させ、常に同一の状態となる構造(以後この構造のことを「状態同期構造」と呼びます)を採用しています。
状態同期構造では同期処理に絞って検査ができる
まず、典型的なWebアプリケーションとして、ユーザーが検索ボックスに文字を入力すると、その検索結果を返すといったものを考えます。通常のWebアプリケーションであれば、検索ボックスに入力された文字をAjaxリクエストでサーバーに投げ、返ってきた検索結果を表示するといった流れになります。
一方で状態同期構造の場合、Ajaxリクエストを投げるのではなく、次のような動作を組み込みます。まず、検索ボックスに入力された文字をブラウザ側で「状態」として保持します。この状態はブラウザとサーバーで同期されているため、すぐに検索文字がサーバー側にも届きます。検索文字を受け取ったサーバーは検索を行い、その結果をサーバー側に書き込みます。検索結果はブラウザ側に同期され、ブラウザが検索結果を表示します。
一見すると状態同期構造は一手間多いですが、この構造ではブラウザ側に実装するアプリケーションロジック(ここでは検索条件を受け付けて結果を表示する仕組みのこと)は直接的には通信を行いません。そのため、もし同期処理が正しく行われるのであれば、通信に起因する問題の影響を受けなくなります。例えば、一般的なWebアプリケーションにおいて、Ajaxで検索結果を問い合わせている時に、一時的にネットワークが切れるとどうなるでしょうか? 通常はリトライ処理が必要になります。一方、状態同期構造におけるアプリケーションロジック側には通信エラーに対する処理が必要ありません。
実際のアプリケーションでは切断対策だけだと不十分で、複雑な処理を行う必要があります。通信ロスやそれに伴うリトライ処理、応答タイミングといった状況からのリカバーを網羅的に対応することは大変困難です。状態同期構造であれば、アプリケーションロジックは処理したいことに集中でき、見通しの良い設計を進める上で、力を発揮します。
状態同期構造にはこのような利点がありますが、同期処理が正しく動作していることに強く依存しているため、同期処理を正しく記述して実装できるかどうかがとても重要です。しかし、先の例のような簡単なアプリケーションでも、ブラウザ側が書き込んだ検索文字を送信した直前・直後に通信が瞬断した場合や、通信切断中に検索文字が変更した場合、通信や並行処理の関係で処理が前後した場合など、さまざまなケースが考えられます。つまり、通信ロスやそのタイミング問題を網羅的に検査することは、状況が多岐にわたるため難しいと言わざるを得ません。一方で、状態同期構造における同期処理自体はアプリケーション全体から見ればごく一部分です。また、アプリケーションロジックから分離しており、仕様変更の影響も受けにくい処理です。そのため、この同期処理だけに時間をかけてモデル検査を用いた網羅的なテストを行うことができます。