サーバー送信イベント(Server-Sent Events、SSE)とは、Webブラウザーとサーバー間の一方向の非同期通信方法のことです。最近、サーバー送信イベントは、リアルタイム通信の実現によく利用されています。本文では、サーバー送信イベントを詳しく解説した上、それを実現する方法を皆さんに紹介します。
サーバー送信イベント(Server-Sent Events)とは
サーバー送信イベント(Server-Sent Events、SSE)とは、Webブラウザーとサーバー間の一方向の非同期通信方法のことです。この通信方法では、サーバーがブラウザーに対してイベントをプッシュ送信でき、ブラウザーはサーバーから送信されたイベントを受信して処理できます。
SSEはHTTPプロトコルに基づいているため、サーバーとブラウザー間は長時間接続を維持でき、テキスト形式でデータ送受信を行います。長時間接続でもリソース消費が少ないため、リアルタイムな通信に向いているのが特徴です。
Server-Sent Eventsの利用シーン
最近、リアルタイムの通信を実現するために、サーバー送信イベントがよく利用されるので、比較的に人気な通信技術になっています。実際には、サーバー送信イベントは、リアルタイムの通信の実現だけに機能しているわけではなく、他にも様々な役割を果たすこともできます。一般的には、サーバー送信イベント(SSE)の利用シーンは次のようになります。
リアルタイム通信の実現: 従来のHTTP通信ではクライアントからのリクエストに対してのみサーバーがレスポンスを返すことで、ステートレスになりますが、SSEを使うことでサーバーからクライアントへリアルタイムにデータをプッシュできます。これによりチャットやライブ更新などが実装できます。
サーバー負荷の軽減: 従来クライアントが周期的にポーリングしていた場合、頻繁なリクエスト送信でサーバー負荷が高くなります。SSEなら長時間接続を使い負荷を抑えられます。
データ通信の効率化: ポーリングではサーバー側に更新がない場合でも頻繁にリクエストを送信します。SSEなら更新時のみデータを送信するので通信効率が良いです。
ストリーミング通信: SSEではHTTPを利用してストリーミングでデータを送受信できます。ビデオや音声などのストリーミングにも利用できます。
ブラウザーの対応: 主要ブラウザーがSSEに対応しているため、特別なライブラリなしに利用できるのが強みです。
このような理由から、リアルタイムWebアプリケーションを開発する際だけではなく、他の場面でもSSEが有用な通信手段になる可能性もあると言えます。
JavaScriptでServer-Sent Events(サーバー送信イベント)の実装
ブラウザー側ではJavaScriptのEventSourceオブジェクトを使ってSSEを受信し、サーバー側はHTTPのレスポンスヘッダーを操作してストリーム形式でデータを送信します。
Server-Sent Events (SSE) のContent-Type
Server-Sent Events (SSE) は、サーバーからクライアントへの一方向の通信を実現するストリーミングデータの伝送方式です。SSEのレスポンスヘッダのContent-Typeには以下のように指定します。
Content-Type: text/event-stream
この値はSSEの仕様で定められており、クライアントがSSEのストリームデータであることを認識するために必要となります。
サーバー側の実装
- HTTPレスポンスヘッダーに以下を設定
- Content-Type: text/event-stream
- Cache-Control: no-cache
- Connection: keep-alive
- データはイベントストリーム形式で送信
- id: イベントの固有ID
- event: イベント名
- data: 送信データ
- flushメソッドでデータをフラッシュ
【サーバー側のサンプルコード】
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
while(true){
// データをJSON形式で作成
$data = json_encode(['message' => 'Hello!', 'time' => date('r')]);
// データを書き出し
echo "event: message\n";
echo "data: {$data}\n\n";
ob_flush();
flush();
// 一定間隔でデータを送信
sleep(1);
}
クライアント側の実装
- EventSourceオブジェクトを生成
- new EventSource(URL)
- addEventListenerでイベントを listens
- イベントハンドラで受信データを処理
- SSE接続が切れた時の処理
サーバー送信イベント(SSE)の簡単な実装例は以下のようになります。
【クライアント側のサンプルコード】
// EventSourceオブジェクトを生成
const eventSource = new EventSource('/sse-endpoint');
// メッセージイベントのリスナーを設定
eventSource.addEventListener('message', (e) => {
const data = JSON.parse(e.data);
console.log(data);
});
// SSEが切断された時の処理
eventSource.onerror = () => {
console.log('SSE disconnected!');
eventSource.close();
};
このようにサーバー側でHTTPレスポンスをストリーミング形式にし、クライアント側でEventSourceを使ってイベントリスナーを登録するのが基本的な実装パターンです。
Apidogで簡単にサーバー送信イベントを実装
Apidogは、サーバー送信イベントに対応できるAPIクライアントです。Apidogを使うことで、非常に直感的な操作で、サーバー送信イベントを実装する事ができます。コードを書かずにサーバー送信イベントを実装したい場合は、Apidogは一番適切なソリューションになると思います。
Server-Sent Events接続の開始
SSE 接続を開始するには、HTTP プロジェクトで新しい API を作成します。リクエストの送信後、レスポンスの Content-Type
に text/event-stream
が含まれている場合、Apidog は自動的に返されたデータを SSE イベントとして解析し、新しいタイムラインビューでレスポンスの内容をリアルタイムに更新します。
後処理でメッセージ内容の抽出
現在のAPIの後処理でカスタムスクリプトを追加して、各 SSE イベントから特定のフィールド値を抽出し、完全な文字列に連結します。
上記の図に示した APIを例に取ると、この APIで返されるメッセージには JSONデータが含まれています。 answer
フィールドからパラメーターの内容を抽出して、完全なテキストに連結します。
カスタム スクリプトに以下の例のコードを記述します。
// レスポンス テキストを取得
const text = pm.response.text()
// テキストを行に分割
var lines = text.split('\n');
// "content"パラメータを格納する空の配列を作成
var contents = [];
// 各行を反復処理
for (var i = 0; i < lines.length; i++) {
const line = lines[i];
// "data:"で始まらない行はスキップ
if (!line.startsWith('data:')) {
continue;
}
// JSON データを解析
try {
var data = JSON.parse(line.substring(5).trim()); // 先頭の "data: " を削除
// "choices" 配列から "content" パラメーターを取得し、配列に追加
contents.push(data.choices[0].delta.content);
} catch (e) {
// 有効なJSONデータでない場合は現在の行を無視
}
}
// "content" パラメーターを join() メソッドを使用して連結
var result = contents.join('');
// 結果を本文の "Visualize" タブに表示
pm.visualizer.set(result);
// 結果をコンソールに出力
console.log(result);
リクエストの送信後、連結されたテキストは「コンソール」で確認できます。
まとめ
本記事では、Server-Sent Events(SSE)について詳しく解説しました。
- SSEはHTTPプロトコルに基づく一方向の非同期通信方式
- サーバーからクライアントへのプッシュ通信が可能
- リアルタイム通信の実現やサーバー負荷軽減などに活用できる
- 主要ブラウザーに標準対応しており、JavaScriptのEventSourceで実装可能
- サーバー側ではレスポンスヘッダを設定し、イベントストリーム形式でデータを送信
- クライアント側ではEventSourceでストリームを受信し、イベントリスナーを登録
SSEはシンプルさと高パフォーマンスが特徴的な通信方式です。リアルタイムWebアプリケーションはもちろん、様々な用途に活用できるでしょう。一方で双方向通信が必要な場合はWebSocketsを利用する必要があります。
今後ますますリアルタイム性が求められるWebアプリケーション開発において、Server-Sent Eventsの理解と実装スキルは重要になってくると考えられます。