WebSocket API
API Gateway の WebSocket API でサーバーレスなリアルタイム双方向通信を実現する仕組み
AWSリアルタイム
WebSocket API とは
API Gateway の WebSocket API は、サーバーレスアーキテクチャでリアルタイム双方向通信を実現する仕組みである。チャット、通知、ダッシュボードのリアルタイム更新など、サーバーからクライアントへのプッシュ配信が必要なユースケースで使われる。
通常の REST API はリクエスト/レスポンスの 1 往復で完結するが、WebSocket API は接続を維持し、サーバーとクライアントが任意のタイミングでメッセージを送受信できる。
アーキテクチャ
[クライアント] ←WebSocket→ [API Gateway] → [Lambda]
→ [DynamoDB (接続管理)]
ルート:
$connect → ConnectHandler (接続 ID を DynamoDB に保存)
$disconnect → DisconnectHandler (接続 ID を削除)
$default → MessageHandler (メッセージを処理)
sendMessage → SendHandler (カスタムルート)
接続管理
WebSocket API では、接続中のクライアントを DynamoDB で管理する。
// $connect: 接続時に接続 ID を保存
export const connectHandler = async (event: APIGatewayProxyEvent) => {
await ddb.send(new PutCommand({
TableName: 'Connections',
Item: {
connectionId: event.requestContext.connectionId,
connectedAt: new Date().toISOString(),
},
}));
return { statusCode: 200 };
};
// サーバーからクライアントにメッセージを送信
const apigw = new ApiGatewayManagementApiClient({
endpoint: `https://${domainName}/${stage}`,
});
await apigw.send(new PostToConnectionCommand({
ConnectionId: connectionId,
Data: JSON.stringify({ message: 'Hello!' }),
}));
ブロードキャスト (全クライアントに送信)
// DynamoDB から全接続 ID を取得し、それぞれにメッセージを送信
const connections = await ddb.send(new ScanCommand({ TableName: 'Connections' }));
await Promise.allSettled(
connections.Items!.map(conn =>
apigw.send(new PostToConnectionCommand({
ConnectionId: conn.connectionId,
Data: JSON.stringify({ message: 'Broadcast!' }),
})).catch(async (err) => {
if (err.statusCode === 410) {
// 410 Gone: 接続が切れている → DynamoDB から削除
await ddb.send(new DeleteCommand({
TableName: 'Connections',
Key: { connectionId: conn.connectionId },
}));
}
})
)
);
SSE との使い分け
| 観点 | WebSocket API | SSE (Server-Sent Events) |
|---|---|---|
| 通信方向 | 双方向 | サーバー → クライアント |
| AWS 実装 | API Gateway WebSocket | Lambda Function URL |
| 接続管理 | DynamoDB で自前管理 | 不要 |
| 適するケース | チャット、ゲーム | 通知、ダッシュボード |
WebSocket API の関連書籍も参考になる。