AI・機械学習
中級

Server-Sent Events(SSE)(サーバーセントイベンツ)

HTTPベースの単方向ストリーミングプロトコル。サーバーからクライアントへテキストベースのイベントを持続的に送信でき、LLM APIのトークンストリーミングで標準的に採用されている通信方式。

0 回閲覧
0 いいね

Server-Sent Events(SSE)とは

Server-Sent Events(SSE)は、W3Cが標準化したHTTPベースの単方向ストリーミングプロトコルです。サーバーからクライアントへ持続的にイベントを送信でき、WebSocketのような双方向通信は不要だがサーバープッシュが必要な場面で使われます。LLMのトークンストリーミングでは、OpenAI・Anthropic・Google・Mistral・Cohere など主要APIプロバイダすべてがSSEを採用しており、事実上の業界標準です。

SSEの基本仕様

HTTPレスポンスヘッダ

SSEレスポンスは通常のHTTPレスポンスですが、Content-Typeが text/event-stream に設定されます。

ヘッダ値目的
Content-Typetext/event-streamSSEストリームであることを宣言
Cache-Controlno-cacheプロキシやCDNによるキャッシュを防止
Connectionkeep-aliveTCP接続を維持
Transfer-Encodingchunkedチャンク転送エンコーディング

イベントフォーマット

各イベントは改行区切りのテキストフィールドで構成されます。

  • data: イベントのペイロード(複数行可)
  • event: イベント種別(省略時は「message」)
  • id: イベントID(再接続時のラストイベントID送信に使用)
  • retry: 再接続間隔(ミリ秒)

イベント間は空行(\\n\\n)で区切られます。

LLM APIにおけるSSEの使い方

OpenAI Chat Completions API

OpenAIのストリーミングレスポンスでは、各SSEイベントの data フィールドにJSON形式の ChatCompletionChunk オブジェクトが含まれます。choices[0].delta.content にトークンテキストが格納され、最後に data: [DONE] が送信されてストリーム終了を通知します。

Anthropic Messages API

AnthropicのSSEイベントは event フィールドでイベント種別を区別します。content_block_delta イベントの delta.text にトークンが含まれ、message_stop で完了を通知します。入力トークン数は message_start の usage.input_tokens で、出力トークン数は message_delta の usage.output_tokens で確認できます。

SSE vs WebSocket vs gRPC

比較項目SSEWebSocketgRPC Streaming
通信方向単方向(サーバー→クライアント)双方向双方向
プロトコルHTTP/1.1, HTTP/2ws:// / wss://HTTP/2
データ形式テキスト(UTF-8)テキスト or バイナリProtocol Buffers
自動再接続ブラウザAPI内蔵手動実装が必要ライブラリ依存
ブラウザ対応EventSource APIWebSocket APIgrpc-web経由
プロキシ透過性高い(通常のHTTP)低い(Upgrade必要)中程度
同時接続上限HTTP/1.1: 6本/ドメイン制限なし制限なし
オーバーヘッドテキストベースでやや大フレーミングのみ最小(バイナリ)

LLMのトークンストリーミングには単方向送信で十分なため、実装の簡潔さ・プロキシ透過性・ブラウザ標準APIの3点からSSEが最適解とされています。

ブラウザでのSSE受信

EventSource API

ブラウザ標準の EventSource APIを使えば、数行のJavaScriptでSSEストリームを受信できます。自動再接続機能が内蔵されており、ネットワーク切断時に retry フィールドで指定された間隔で自動的に再接続を試みます。

fetch + ReadableStream

EventSource APIはPOSTリクエストに対応していないため、LLM APIの呼び出し(通常POST)には fetch APIと ReadableStream を組み合わせる方法が一般的です。レスポンスボディを getReader() で取得し、TextDecoder でデコードしてSSEイベントをパースします。

SSEの制約と対策

HTTP/1.1の同時接続制限

HTTP/1.1ではブラウザが1ドメインあたり最大6本のTCP接続しか開けないため、SSEストリームが1本開くと残り5本になります。HTTP/2ではストリーム多重化により実質的に制限がなくなるため、SSEを使うAPIエンドポイントはHTTP/2対応が推奨されます。

プロキシ・CDNのタイムアウト

Nginx(デフォルト60秒)、Cloudflare(100秒)などのリバースプロキシは長時間接続をタイムアウトする場合があります。LLMの長い回答(2,000トークン以上)ではストリーム持続時間が60秒を超えることがあるため、プロキシのタイムアウト値を適切に設定する必要があります。

FAQ

Q1: SSEはHTTP/2でも使える?

A1: はい。HTTP/2ではストリーム多重化により、1つのTCP接続上で複数のSSEストリームを並行処理できます。HTTP/1.1の6接続制限も解消されるため、HTTP/2環境でのSSE利用が推奨されます。

Q2: SSEで画像やバイナリデータは送れる?

A2: SSEはUTF-8テキスト専用です。バイナリデータを送る場合はBase64エンコードが必要ですが、オーバーヘッドが33%増加します。マルチモーダルLLMの画像出力にはWebSocketまたはgRPCの使用が適切です。

Q3: SSEストリームが途切れた場合の再接続は?

A3: ブラウザの EventSource APIは自動再接続機能を持ち、サーバーの retry フィールドで間隔を制御できます。fetch + ReadableStream の場合は手動でリトライロジックを実装し、最後に受信した id を Last-Event-ID ヘッダで送信して途中から再開します。