SSE と WebSocket:適切なストリームの選び方
SSE と WebSocket の比較
SSE と WebSocket:どちらのリアルタイム方式を使うか | We.Inc
Server-Sent Events と WebSocket を比較します。EventSource と WebSocket の並列比較、再接続、バイナリデータ、接続数の上限、判定ツール、そして両方の最小限の Node サーバーを紹介します。
Server-Sent Events は通常のHTTPレスポンスでサーバーからブラウザーへテキストをストリーミングし、EventSource API は自動で再接続します。WebSocket は接続をアップグレードして双方向のチャネルにし、テキストもバイナリも両方向に運べます。フィード、通知、進捗にはSSEを、ブラウザーから頻繁にメッセージを送り返す必要があるときはWebSocketを使いましょう。
並べて比較
- 機能
- Server-Sent Events
- WebSocket
- ブラウザーのAPI
- EventSource
- WebSocket
- プロトコル
- 通常のHTTP、text/event-stream
- HTTP Upgrade の後に ws:// または wss://
- データ
- UTF-8 テキストのみ
- テキストまたはバイナリ
- 再接続
- 自動。Last-Event-ID で再開
- 自分で実装する
- HTTP/1 での同時接続数
- ブラウザーごと、ドメインごとに 6
- 各ブラウザーが定める別の上限
自分の機能にどちらが必要かわからない場合は、下の判定ツールで当てはまる項目にチェックを入れてください。上の表と同じ規則を適用し、どのAPIが合うか、そしてその理由を示します。
- 自分の機能に当てはまる項目にそれぞれチェックを入れます。
- 推奨と、その理由を読みます。
- さらに下のセクションから、対応するクライアントとサーバーのコードをコピーします。
- URLとイベント名を自分のものに変え、Node でサーバーを実行します。
- アイドル状態のプロキシに切断されないよう、SSEのストリームでは 15 から 30 秒ごとにコメント行(コロンの後にテキスト)を送りましょう。
- SSEのすべてのイベントに id を付けましょう。ブラウザーは再接続時にその値を Last-Event-ID ヘッダーで送り返すので、サーバーは取りこぼした分を再送できます。
- 可能ならSSEは HTTP/2 で配信しましょう。HTTP/1 の6接続の上限は、サイトで開いているすべてのタブで共有されるためです。
- WebSocket では、大量のデータを一気に送る前に bufferedAmount を確認しましょう。API自体には背圧の仕組みがありません。
よくある質問
SSEでブラウザーからサーバーにデータを送れますか?
ストリーム自体では送れません。イベントストリームはサーバーからクライアントへ一方向にしか流れないので、ブラウザーは通常の fetch リクエストでメッセージを送ります。チャットのような双方向の通信には、WebSocket のほうがすっきり合います。
EventSource の再接続を止めるには?
クライアントで close() を呼びます。サーバー側からは、HTML標準によると 204 No Content のレスポンスを返すと、クライアントに再接続をやめるよう伝えられます。
EventSource で Authorization ヘッダーを送れますか?
いいえ。コンストラクターが受け取るのはURLと、withCredentials だけを設定できるオプションオブジェクトです。独自のヘッダーが必要なら、Cookie、URLに含めた短期間のトークン、または fetch ベースの読み取り処理を使いましょう。
WebSocket がある今、SSEは時代遅れですか?
いいえ。text/event-stream 形式は、プロトコルを切り替えずに通常のHTTPサーバー、プロキシ、認証をそのまま通るので、一方向のフィードには今でも良い選択です。
サーバーのリソース消費が少ないのはどちらですか?
どちらもクライアントごとに長時間続く接続を1つ保つので、差は小さいです。それより重要なのは、ホスティング先が長時間のレスポンスやプロトコルのアップグレードをそもそも許可しているかどうかなので、まずリクエスト時間の上限を確認しましょう。
Server-Sent Events の仕組み
- サーバーは通常のGETに Content-Type text/event-stream で応答し、レスポンスを開いたままにします。各メッセージは event:、data:、id: などの数行で構成され、空行で終わります。1つのメッセージ内の複数の data: 行は改行でつなげられます。
- ブラウザーの EventSource はそのストリームを解析し、名前のないメッセージには message イベントを、それ以外には名前付きのイベントを発火させ、切断後は自動で再接続します。retry: 行で、再試行までの待ち時間をミリ秒で設定できます。
WebSocket の仕組み
- クライアントは Upgrade ヘッダー付きのHTTPリクエストから始め、サーバーは 101 Switching Protocols で応答します。それ以降、接続はHTTPではなくWebSocketのフレームを運び、どちら側もいつでも送信できます。
- その自由にはコストがあります。再接続の処理、メッセージ形式(多くは type フィールド付きのJSON)、ハートビートを自分で書く必要があります。Upgrade ヘッダーを転送しないプロキシがあると、接続は始まる前に止まってしまいます。
簡単な目安
- ブラウザーが主に受信するだけならSSEを選びましょう。試合のライブスコア、ビルドログ、注文状況、通知、ストリーミングされるテキストはすべてこれに当てはまります。
- ブラウザーが受信と同じくらい送信する場合や、データがバイナリの場合はWebSocketを選びましょう。マルチプレイヤーゲーム、共同編集エディター、チャットルームはすべてこちらに当てはまります。
Server-Sent Events:最小限のコード
素の Node で書くSSEサーバー
ライブラリは不要です。レスポンスは開いたままで、1回の書き込みが1つのイベントになり、コメント行がアイドル状態のプロキシによる切断を防ぎます。
ブラウザーでの EventSource
addEventListener はストリームのイベント名を使います。再接続はあなたのコードなしで行われます。
WebSocket:最小限のコード
ws パッケージを使ったWebSocketサーバー
npm install ws でインストールします。受け取ったメッセージをすべて大文字にして、送信したクライアントに返します。
簡単な再接続付きの、ブラウザーでのWebSocket
EventSource と違い、自動で再接続されないので、close の後に少し待って新しいソケットを開きます。
ブラウザーから多くのメッセージを送り返す(1秒に数回以上)
データがバイナリである(音声のチャンクやゲーム状態のバッファーなど)
接続が切れた後、クライアントが取りこぼしたイベントに追いつく必要がある
通信が、通常のHTTPしか扱えないプロキシやホスティングを通る
Server-Sent Events が合っています。チェックした項目に双方向のチャネルが必要なものはなく、EventSource なら再接続と再開が無料で手に入ります。
WebSocket が合っています。ブラウザーからの頻繁なメッセージやバイナリデータが必要で、これはイベントストリームでは運べません。
あなたの機能に合うのはどちら?
あなたの機能に当てはまるものにチェック
推奨
Server-Sent Events
WebSocket
無料で始める · クレジットカード不要
関連: ガイド|Webマーケティングと集客を学ぶ
製品
ご利用いただける方
機能
リソース
会社情報
サイトマップを見る