リアルタイム通信 — WebSocket・gRPC ストリーミング・WebRTC
SSE・WebSocket・gRPC ストリーミング・WebRTC のどれを使うか
一言でいうと
サーバーが話すだけならSSE、双方がたびたび話すならWebSocket、サービス間の契約が重要ならgRPCストリーミング、人の声を数十ms以内に運ぶならWebRTCです。
なぜ必要なのか
リアルタイム機能を作るとき、最初に下す決定が伝送路で、一度選ぶと変えにくいものです。クライアントコード、認証方式、プロキシの設定、観測ツールが、すべてその選択に結びつくからです。ところが、この決定は、よく「最近はみんなWebSocketを使っているようだから」のような理由で下されます。それぞれの伝送路が、何をタダで与えてくれて、何を自分で作らせるのかを、並べて見ると、選択の根拠が生まれます。
どう動くのか
HTML標準のServer-Sent Eventsは、普通のHTTP応答を終わらせずに、text/event-streamとして書き続ける方式です。サーバーからクライアントへの一方向で、テキストだけを運びます。その代わり、ブラウザーのEventSourceは、切れると自分で再接続し、最後に受け取ったイベント番号をLast-Event-IDヘッダーで知らせる再開のルールが、標準に入っています。普通のHTTPなので、プロキシと認証をそのまま通ります。LLMのトークンストリーミングAPIが、この方式をよく使います。ただし、EventSourceは、ユーザー定義のリクエストヘッダーを付けられず、HTTP/1.1では、ブラウザーのドメインごとの接続数制限(通常6個)に引っかかります。HTTP/2では、ストリームとして重ねて載せられるので、この制限はなくなります。
WebSocketは、双方向で、バイナリを運び、メッセージの境界を守ってくれます。その代わり、再接続、再開、バックプレッシャー、リクエストと応答の対応づけを、すべてアプリケーションが作る必要があります。前のモジュールで自分で作った、連番・リングバッファー・ジッター付きバックオフが、それです。HTTP/1.1のUpgradeで始まるので、中間機器がUpgradeを通してくれる必要があります。
gRPCストリーミングは、protoで決めた契約、期限、ステータスコード、フロー制御、リトライポリシーを与えてくれます。サービス間の通信には、最も多くのものをタダで与えてくれます。しかし、ブラウザーは、HTTP/2のトレーラーを扱うAPIがないので、gRPCを直接話せず、間に変換層を置くgRPC-Webは、クライアントストリーミングと双方向ストリーミングをサポートしていません。
WebRTCは、前の3つとは層が違います。UDPの上で、遅れたデータを捨てられ、Opusコーデックとジッターバッファーとエコーキャンセルがブラウザーに入っていて、人の声を、最も短いレイテンシで運びます。その代わり、シグナリング、ICE、TURNサーバーを、自分で運用する必要があります。
| 基準 | SSE | WebSocket | gRPCストリーミング | WebRTC |
|---|---|---|---|---|
| 方向 | サーバー → クライアント | 双方向 | 4つの形 | 双方向(ピア間) |
| ブラウザー | 標準でサポート | 標準でサポート | gRPC-Webで一部のみ | 標準でサポート |
| 再接続・再開 | 標準にあり | 自前 | 自前(リトライは確定前だけ) | ICE再起動 |
| 遅れたデータの破棄 | 不可 | 不可(TCP) | 不可(TCP) | 可能 |
| 運用負担 | 最も小さい | 中程度 | 中程度(プロキシのHTTP/2) | 最も大きい(TURN) |
表にないものも、1つ取り上げておきます。HTTP/3の上のWebTransportは、ブラウザーでQUICストリームと信頼性のないデータグラムを一緒に使えるようにする新しいAPIで、WebSocketの簡単なサーバー構造と、WebRTCの遅れたデータの破棄を、あわせて狙っています。まだすべてのブラウザーとサーバー構成で使えるわけではないので、導入するには、対象の環境で先に確認する必要があります。新しい技術が出ても、選択の問いは同じです。方向、ブラウザーのサポート、遅れたデータを捨てられるか、そして、運用する人が耐えられるか、です。
現場での姿
音声AIサービスは、よく2つ以上を混ぜます。ブラウザー・携帯電話とサーバーの間の声はWebRTCで、サーバー内部の認識・合成エンジンとはgRPC双方向ストリーミングやWebSocketで、画面に出す字幕とトークンはSSEやWebSocketで運びます。伝送路を1つに統一するより、区間ごとに必要な性質、つまり、遅れたものの破棄、契約と期限、ブラウザーのサポートを選ぶほうが、結果がよくなります。
認証と観測も、伝送路によって変わります。SSEとgRPCは、リクエストごとにヘッダーがあるので、既存の認証ミドルウェアとアクセスログをそのまま使えます。WebSocketは、ハンドシェイクを1回行ったあとはヘッダーがないので、トークンが期限切れになる長い接続では、メッセージで再認証するか、接続を切って再接続させる必要があり、メッセージ単位の指標を自分で作る必要があります。
選択を覆させる、よくある理由もあります。社内プロキシがWebSocket Upgradeを塞いでSSEに後退したり、UDPが塞がれた網のために、WebRTCにTURN over TCP/TLS 443を加えたりします。最初から「この網で動くか」を確認することが、伝送路選択の最初の段階です。
次のクイズですること
状況ごとに適切な伝送路を選び、それぞれの伝送路がタダで与えてくれるものと、自分で作る必要があるものを区別します。