2015年4月24日金曜日

サーバサイドで WebSocket を実装するための基礎

比較的シンプルな仕様である WebSocket ですが、サーバサイドフレームワークからの視点で見ると留意しなければならない点が幾つかあります。


多数の同時接続

一旦接続が成立すると、どちらかから切断しないかぎり、そのまま保持されます。WebSocket を使うサーバサイドは、同時に接続するクライアントの数が膨大になることを想定しなければなりません。いわゆる C10K 問題(クライアント1万台問題)です。

これを軽減するには、Linux では epoll システムコール、BSD の場合は kqueue システムコールなどの多重I/Oを使ったソケットの監視が必須となります。


また、リスエストを処理する部分については、1つの重い処理に引きずられて他のリクエストのレスポンスが遅くなっていはいけませんので、1リクエストを処理するのに1スレッド(または1プロセス)を割り当てることを考えなければなりません。スレッドもリソースを消費するので、無尽蔵に生成されないよう注意する必要があります。

 ※ 1つの接続に対し常時1つのスレッドが必要という意味ではありません


このような理由で、シングルスレッドのイベント駆動型モデルの実装(node.jsなど)には問題があると言えるでしょう ※1。但し、アプリが実行する処理が単純で、重い処理が全くないという場合はこの問題は当てはまりませんが、どのような要求にも対応すべき必要がある開発フレームワークとしてはあまり考えられないアーキテクチャだと思います。

 ※1   サーバをマルチプロセス化するという軽減策もでてきているが根本的な解決策ではないでしょう

キープアライブ

通信相手がダウンしていないかどうか、または通信路が確立されているかどうかをチェックするための定期的な通信。

  TCPにもキープアライブの機能がありますが、ここはアプリケーションレイヤーの話です。

WebSocket では長時間接続し続けることが想定されています。通信相手のプログラムがダウンしていなくとも、無通信状態が長く続くと通信路の途中にあるルータなどの機器がポートを閉じてしまうケースがあります。

これを回避するため、無通信時間があまり長くならないようピン/ポンフレームを送受信しなければなりませんが、2015年4月現在、ブラウザ上のスクリプトからこれらのフレームを送る仕組み(API)はありません。

従って、サーバサイドからピン/ポンフレームを定期的または任意のタイミングで送る仕組みが必要となります。


クライアントへのブロードキャスト

チャットアプリを想像すると分かりやすいですが、ある人が書いたコメントはそのグループ全員に直ちに通知されます。このようにメッセージを多数のクライアントへ一括送信できる「ブロードキャスト」の仕組みが必要です。

解決策として「出版-購読型モデル」のアーキテクチャは考えられます。アプリケーションサーバ自体にこの仕組があることが望まれます。

規模が巨大なシステムの場合は、負荷分散のためにアプリケーションサーバのホストを複数設置することになるので、別のプロダクト(Redisなど)と組み合わせて実現することになるでしょう。

データベースへのアクセス

敢えて書くまでもないかもしれませんが、HTTP/HTML のWebアプリと同様に、データベースとのデータの受け渡しができなければなりません。トランザクションについても機能が実装されているかどうかチェックしましょう。







0 件のコメント:

コメントを投稿