🌵

API Gateway で Websocket 開発(仕組み編)

2024/03/03に公開

概要

API Gateway では Websocket 接続もサポートされている事を知りました。

使い勝手を調べたところ、自分のイメージとは(良い意味で)異なっていました。

この記事では、自分の理解を整理するため、特徴的だと感じた仕様をまとめます。

目次

用語

用語 意味
クライアント API Gawatey へ Websocket 接続を要求する側
サーバー クライアントのWebsocket 通信に応じて、サービスを提供する側

要点

  • 通信プロトコル周り
    • クライアントと API Gateway 間は wss (or ws) プロトコルで通信
    • API Gateway と サーバー間は REST APIで通信
  • サーバー側から API Gateway を介して Websocket クライアントと通信を開始する
    • サーバー側から通信を開始する際、 connection_id という情報を用いて、通信したいクライアントを識別する
    • @connections コマンドを使用して、サーバー側から通信を開始する
      • @connections コマンドの中で、 connection_id を指定する
  • "ルート" 情報で、転送先サーバー側アプリケーションを制御
    • Websocket メッセージの内容に応じて、ルートが決まる
    • ルート別に、「ルートが選択されたときに実行したいサーバー側アプリケーション」を設定できる
      • サーバーレスアプリケーションも設定できる(Lambdaに至っては統合されている)
    • これらの設定により、Websocket メッセージを使って、実行したいサーバー側アプリケーションを制御できる

通信プロトコル周り

クライアント と API Gateway 間は wss(or ws) プロトコルにて通信します。

一方、API Gateway とサーバー間は REST API で通信します。

クライアントとサーバー間の通信プロトコル図

クライアント側では wss (または ws)プロトコルでアプリケーションを開発し、 Websocket の機能を享受できます。

一方、サーバー側では、使い慣れ、フレームワークも実績も豊富な REST API でアプリケーションを開発することが出来ます。

(余談)

API Gateway の Websocket 機能を確認する前では、「wss(or ws) プロトコルを中継する機能」程度に想像していました。
つまり、API Gateway と サーバー間も wss (あたは ws)で通信するものとばかり思っておりました。
調べてみると、上記の通りの実装であり、うまくできているなぁと目から鱗でした。

サーバー側から API Gateway を介して Websocket クライアントと通信を開始する

Websocket プロトコルの強みの一つは、サーバー側から通信を開始できる点です。

通信プロトコル周りで紹介したように、 API Gateway と サーバー間は REST API で通信します。

この点を踏まえ、この章では以下を確認します。

  • サーバー側から、 REST API を使用して、クライアントと通信を開始する仕組み
  • クライアントを識別する方法

サーバー側から通信を開始する

サーバー側から通信を開始する手段として、API Gateway の Websocketでは、@connections コマンドという仕組みが用意されています。

以下は、クライアントへメッセージを送信する @connections コマンドの例です。

//({connection_id} については後述)
POST https://{api-id}.execute-api.{region}.amazonaws.com/{stage}/@connections/{connection_id} 

見ての通り、 @connections というパスを含む API Gateway へ POST リクエストを送信しています。

つまり、@connections というパスを含む API Gateway のエンドポイントへ (REST形式で)リクエストを送信することで、クライアントへの通信を実現します。

connectionsコマンドでサーバー側から通信を開始

自力で POST リクエストを組み立てる他、AWS SDKに、 @connections コマンド用のAPIが用意されています。

次に、通信したいクライアントを識別する方法を確認します。

通信したいクライアントを識別する

クライアント識別するには、 connection_id という情報を使用します。

クライアントを識別する手段として connection_id という情報が用意されています。

connection_idでクライアントを識別

各種 @connections コマンドの詳細は、以下公式ドキュメントを参照ください。

"ルート" 情報で、転送先サーバー側アプリケーションを制御

クライアントから Websocket 通信を受け付けた API Gateway は、処理を行うサーバー側を制御できます。

API Gateway の Websocket API の文脈では、"ルート" と表現します。

Websocket メッセージの内容に応じて、ルートが自動で選択されます。

そして、ルート毎に、処理したいサーバー側アプリケーションを設定できます。

ルート

用意されているルートの種類と、その概説は以下の通りです。

ルート名 概説
$connect ルート Websocket 接続が確立されたときに選択されるルート。接続確立時に実行したい処理は、このルートに紐づける。
$disconnect ルート Websocket 接続が切断されたときに選択されるルート。接続切断時に実行したい処理は、このルートに紐づける。
カスタムルート 開発者が制御できるルート。メインとなる処理は、このルートに紐づける。
$default ルート 上記のいずれにも該当しない場合に選択されるルート。 予期しないメッセージの処理等に活用する。

開発者が制御できる、 "カスタムルート" について、もう少し掘り下げます。

カスタムルートで、メインロジックを更に細かく制御

カスタムルートの仕組みは単純です。

Websocket メッセージ内の特定の値を参照して、ルートを制御します。

公式ドキュメントでは、"特定の値"に action という名前を用いており、本記事もこれに倣います(もちろん、任意の値を設定することも可能です)。

ルート選択式

そして、 action プロパティの値に応じて、実行したいサーバー側アプリケーションを設定できます。

カスタムルート

クォータ

公式ドキュメント に記載の通りです。

特に、以下のクォータには要注意です。

リソースまたはオペレーション デフォルトのクォータ 引き上げ可能
WebSocket API の接続時間 2時間 いいえ

上記クォータは、一つの Websocket 接続単位で設けられます。

  • 1接続辺り、 最大2時間接続可能
  • 言い換えると、10接続だから 1接続辺り 12分 ... というわけではない

感想

API Gateway とサーバー間の通信に REST API を用いる点、最初は戸惑いましたが、理解が進むと色々とメリットが多いように感じました。

REST API に対応していれば、サーバーレスサービスも選択でき、 Lambdaに至っては Websocket APIと統合されています。

メインとなる処理も "カスタムルート" という仕組みで細かく制御可能で、 マイクロサービス化も容易に感じました。

また、試しに作成した過程を こちらの記事 にまとめました。

参考文献

Discussion