Spring Web Reactive | 3. WebSocket | 3.1. WebSocketの概要

WebSocketプロトコルであるRFC 6455は、単一のTCP接続を通じてクライアントとサーバー間に全二重の双方向通信チャネルを確立する標準的な方法を提供します。HTTPとは異なるTCPプロトコルですが、ポート80と443を使用し、既存のファイアウォールルールを再利用できるようHTTP上で動作するように設計されています。

WebSocketの通信は、HTTPのUpgradeヘッダーを使用してWebSocketプロトコルへ切り替えるHTTPリクエストから始まります。次の例は、このやり取りを示します。

GET /spring-websocket-portfolio/portfolio HTTP/1.1
Host: localhost:8080
Upgrade: websocket   (1)
Connection: Upgrade   (2)
Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==
Sec-WebSocket-Protocol: v10.stomp, v11.stomp
Sec-WebSocket-Version: 13
Origin: http://localhost:8080
  • (1) Upgradeヘッダー。
  • (2) アップグレードされた接続を使用します。

通常の200ステータスコードではなく、WebSocketをサポートするサーバーは次のような出力を返します。

HTTP/1.1 101 Switching Protocols   // (1)
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=
Sec-WebSocket-Protocol: v10.stomp
  • (1) プロトコルの切り替え。

ハンドシェイクが成功すると、HTTPアップグレードリクエストの基盤となるTCPソケットは、クライアントとサーバーの両方で開いたままになり、メッセージの送受信を続けます。

WebSocketの動作に関する完全な説明は、この文書の範囲外です。RFC 6455、HTML5のWebSocketの章、またはWeb上の入門記事やチュートリアルを参照してください。

WebSocketサーバーがnginxなどのWebサーバーの背後で動作する場合は、WebSocketアップグレードリクエストを転送する設定が必要になる可能性があります。同様に、アプリケーションがクラウド環境で動作する場合は、WebSocketサポートに関するクラウドプロバイダーのガイドを確認してください。

3.1.1. HTTPとWebSocket

WebSocketはHTTPと互換性を持つように設計され、HTTPリクエストから始まりますが、2つのプロトコルは大きく異なるアーキテクチャーとアプリケーションプログラミングモデルにつながります。

HTTPとRESTでは、アプリケーションは多数のURLでモデル化されます。クライアントは、リクエストとレスポンスの形式でURLにアクセスします。サーバーはHTTP URL、メソッド、ヘッダーに基づいて、適切なハンドラーへリクエストをルーティングします。

一方、WebSocketでは通常、最初の接続URLは1つだけです。その後、すべてのアプリケーションメッセージは同じTCP接続を流れます。これはまったく異なる非同期イベント駆動型のメッセージングアーキテクチャーです。

WebSocketは低レベルの転送プロトコルです。HTTPとは異なり、メッセージ内容のセマンティクスを規定しません。クライアントとサーバーがメッセージの意味に合意しない限り、ルーティングや処理はできません。

WebSocketクライアントとサーバーは、HTTPハンドシェイクリクエストのSec-WebSocket-Protocolヘッダーを通じて、STOMPなどの上位レベルのメッセージングプロトコルをネゴシエートできます。このヘッダーがない場合、クライアントとサーバーは独自の規則を定義する必要があります。

3.1.2. WebSocketを使用するタイミング

WebSocketを使用すると、Webページを動的でインタラクティブにできます。ただし、多くの場合はAjaxとHTTPストリーミングまたはロングポーリングの組み合わせでも、シンプルで効果的な解決策になります。

たとえば、ニュース、メール、ソーシャルフィードは動的な更新が必要ですが、数分ごとの更新でも十分です。一方、共同作業、ゲーム、金融アプリケーションでは、よりリアルタイムな体験が求められます。

レイテンシーだけが判断要因ではありません。ネットワーク障害の監視など、メッセージ量が比較的少ない場合は、HTTPストリーミングやポーリングが効果的です。WebSocketは、低レイテンシー、高頻度、大容量が組み合わさる場合に最適です。

また、インターネット上の制限の厳しいプロキシーがUpgradeヘッダーを転送しなかったり、アイドル状態に見える長時間接続を閉じたりするため、WebSocket通信を妨げる場合があります。このため、ファイアウォール内部のアプリケーションでWebSocketを使用する方が、公開アプリケーションで使用するより判断しやすい場合があります。