0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

リアルタイムWeb通信をシンプルに: SSEの基礎と使い方

Last updated at Posted at 2024-11-11

サーバー送信イベント(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-Typetext/event-stream が含まれている場合、Apidog は自動的に返されたデータを SSE イベントとして解析し、新しいタイムラインビューでレスポンスの内容をリアルタイムに更新します。

sse-chatgpt-1.png

後処理でメッセージ内容の抽出

現在のAPIの後処理でカスタムスクリプトを追加して、各 SSE イベントから特定のフィールド値を抽出し、完全な文字列に連結します。

上記の図に示した APIを例に取ると、この APIで返されるメッセージには JSONデータが含まれています。 answer フィールドからパラメーターの内容を抽出して、完全なテキストに連結します。

sse-chatgpt-2.png

カスタム スクリプトに以下の例のコードを記述します。

// レスポンス テキストを取得
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);

リクエストの送信後、連結されたテキストは「コンソール」で確認できます。

sse-chatgpt-3.png

まとめ

本記事では、Server-Sent Events(SSE)について詳しく解説しました。

  • SSEはHTTPプロトコルに基づく一方向の非同期通信方式
  • サーバーからクライアントへのプッシュ通信が可能
  • リアルタイム通信の実現やサーバー負荷軽減などに活用できる
  • 主要ブラウザーに標準対応しており、JavaScriptのEventSourceで実装可能
  • サーバー側ではレスポンスヘッダを設定し、イベントストリーム形式でデータを送信
  • クライアント側ではEventSourceでストリームを受信し、イベントリスナーを登録

SSEはシンプルさと高パフォーマンスが特徴的な通信方式です。リアルタイムWebアプリケーションはもちろん、様々な用途に活用できるでしょう。一方で双方向通信が必要な場合はWebSocketsを利用する必要があります。

今後ますますリアルタイム性が求められるWebアプリケーション開発において、Server-Sent Eventsの理解と実装スキルは重要になってくると考えられます。

最後まで読んでくださり、ありがとうございました!
この記事を読んで少しでも理解を深めていただければ幸いです!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?