WebSocket は、ブラウザとサーバーの間で持続的な接続を維持し、双方向にデータをやり取りできる通信プロトコルです。HTTP とは設計思想が異なるため、リアルタイム通信の文脈で特によく登場します。
HTTP との違い
通常の HTTP 通信は「クライアントがリクエストを送り、サーバーがレスポンスを返す」という 1 往復で完結します。チャットアプリのように「サーバー側から能動的にデータを送りたい」場面では、HTTP のポーリング(一定間隔で繰り返しリクエストを送る手法)が使われてきましたが、無駄なリクエストが増え、レイテンシも生じやすい方法です。
WebSocket ではまず HTTP のハンドシェイクで接続を確立し、その後は同じ TCP 接続をそのまま使い続けます。接続が維持されている間は、クライアント・サーバーのどちら側からでも任意のタイミングでメッセージを送信できます。都度のヘッダーオーバーヘッドがなく、低レイテンシで継続的なデータ転送が可能です。
プロトコルの成り立ち
WebSocket は RFC 6455 として 2011 年に標準化されました。それ以前は、サーバーからブラウザへのプッシュ通知を実現するために Long Polling や Server-Sent Events といった回避策が使われていました。WebSocket はこれらを置き換える目的で設計されており、スキームには ws://(平文)と wss://(TLS 暗号化)が使われます1。
JavaScript の WebSocket API はブラウザに標準実装されており、new WebSocket(url) でオブジェクトを生成し、open・message・close・error の各イベントにハンドラを登録する形で動作します。サーバー側は Berkeley ソケットを扱える言語であれば実装でき、Node.js・Python・Go などが選ばれることが多いです2。
主な用途
WebSocket が実際に使われている代表的なシナリオは次のとおりです。
| 用途 | 具体例 |
|---|---|
| チャット・メッセージング | Slack、Discord のメッセージ配信 |
| リアルタイムデータ表示 | 株価ティッカー、スポーツスコア速報 |
| 共同編集 | Google Docs のようなドキュメント同時編集 |
| ゲーム | ブラウザベースのマルチプレイヤーゲーム |
| 通知プッシュ | Web アプリ内のアラート配信 |
ブラウザで株価を表示するダッシュボードを作る場合、ポーリングでは数秒ごとに全件取得が必要ですが、WebSocket を使えばサーバーが変動のあった銘柄のデータだけを即座に送信できます。
Server-Sent Events との使い分け
WebSocket に似た技術として Server-Sent Events(SSE)があります。SSE はサーバーからクライアントへの一方向送信に特化しており、HTTP の通常のコネクションを使うため、ロードバランサやプロキシとの相性が良い場面があります。通知の配信や更新フィードのような「サーバー→クライアント」のみで十分なユースケースでは SSE の方がシンプルです。双方向かつ低レイテンシなやり取りが必要な場合は WebSocket を選ぶのが妥当です。
接続管理の注意点
WebSocket の接続は長期間維持されるため、スケールアウト時に設計上の考慮が必要です。複数サーバーにリクエストを振り分けるロードバランサは、スティッキーセッション(同一クライアントを同一サーバーへ固定)で扱うか、Redis などのメッセージブローカーを経由してサーバー間でメッセージを共有する構成が求められます。
接続数が増えるとサーバー側のファイルディスクリプタ・メモリの消費も増加します。接続タイムアウトの設定と、切断時の再接続処理をクライアント側で実装しておくことを推奨します。
スケール設計と並行して、認証トークンの検証タイミングにも注意が必要です。HTTP のハンドシェイク時点でトークンを検証しておかないと、接続確立後に不正なクライアントを切り離す処理が複雑になります。