実際に動いているチャットサービス(小規模)のインフラ構成を公開 | AWS イベントソーシング Auth0
はじめに
個人開発で制作し先日(2020/11/08)に初めのバージョンを公開したチャットサービス Someteria - Webサイト横断チャット (Chrome拡張) のインフラ構成を掲載します。 現状の総インストール数は8人(2020/11/10 時点)、生まれたてのサービスなので本格的な商業的サービスで適応できるかは保証しかねます。しかし、ミニマムにリアルタイムなメッセージの送受信基盤を作る際の一例として参考になれば幸いです。
インフラ構成図
概略
- AWSのサーバレスフレームワークのSAMを利用
- Webサーバーの管理は基本しない
- RESTfulなHTTP APIとしてのエンドポイントとWebSocketのエンドポイントがある
- メッセージPush通知にWebSocketを利用
- データストレージはDynamoDBとElasticsearchを利用
- イベントソーシングの考えをベースにしている (後述)
- 認証処理はAuth0 (IDaaSの一つ)を利用
DBまわり, イベントソーシング
書き込み要件と読み込み要件を分離するためにイベントソーシングのパターンを適応し、データソースを分けています。
流れ:
- API Gatewayから書き込み系の処理のLambdaを起動
- Lambdaから書き込みイベントをDynamoDBに保存
- DynamoDB Streamsをトリガーとして以下のLambdaをそれぞれ起動
- Elasticsearchに表示用の非正規化されたデータを反映・構築
- ブラウザに対してWebSocket経由で更新メッセージを送信
- 後ほど、読み込み系の処理のLambdaが表示用データにアクセス
少し回りくどくなりますが、1.の書き込み系の処理を行うLambdaと、3.の読み込み要件を担うLambdaとで関心を分離できます。そのおかげで実際の経験として、当初はブラウザからポーリングして取得していたデータを、サーバーからのプッシュにするようにする変更があったのですが、その際に1.の書き込み処理用のLambdaの変更は一切不要でした。
認証・ユーザ情報周り
認証にはAuth0 (IDaaS)を利用し、Google, TwitterなどのプロバイダーとOpenID Connectのフローにより連携しています。 フロントのアプリケーションが直接Auth0のエンドポイントとやりとりし認証しトークン(JWT)を受け取ります。そのJWTをサーバーサイドに送りアクセス可否を判断します。
Elasticsearchへユーザー情報の同期
Auth0に保存されるユーザー情報(ユーザ名, アイコンURLなど)は、Auth0のログイン時に起動できるフックによってElasticsearchに同期しています。 Auth0上のユーザー情報はAuth0のAPIから直接アクセスもできます。しかしユーザー情報は頻繁にアクセスするのでAPIのレートリミットを超えないようにするためそうしています。
サーバープッシュ WebSocket
サーバーからのプッシュ通知はAPI GatewayのWebSocket APIを使用しています。クライアントがWebSocket APIに接続した際に得られるコネクションIDとメッセージサブスクリプションの情報をDynamoDBに保存します。後ほど、関連する更新イベントが起きた場合にコネクションIDを取得してクライアントに通知できます。
その他特徴
- AWS Lambdaをベースとしたサーバレスアプリなので、サーバーのスケーリングをAWSに委ねられる
- AWS SAMはCloudFormationによってコードベースでインフラを定義できるので、再現性が高い
- ステージング環境などの複製環境をターミナルのコマンドから構築できる
まとめ
いかがだったでしょうか。チャットに限らず、リアルタイムなメッセージパッシングを実装する機会があれば、参考にしていただければと思います。
Web横断チャットサービスSometeriaも是非お試しください。