[イベント駆動型アーキテクチャ] アーキテクチャ例
さて、前回は Salesforce の提供する、Heroku のアドオン "Apache Kafka on Heroku" と Salesforce Platform 上で稼働しているイベントバスの "プラットフォームイベント(Platform Events)" について紹介しました。今回は、わたしの考えたチケット予約サイトのアーキテクチャで、実際の実装時の利用例について見てみましょう。
ちなみに、考えただけなので、まだ実装されたことはありません。誰かに実装してほしい。
この予約サイトは、外部にマイページや認証基盤(IDaaS)を持つ、Heroku で構成されたアプリケーション構造です。全てのイベントを処理する際に、必ず "Apache Kafka" がハブとなって、各処理と連携する仕組みです。
各所、分解して詳解します。
1. SPA アプリと、実際の接続点
SPA(Single Page Application) で構成された、いわゆるブラウザ上でのリッチWebアプリケーションと、その接続先たる API Manager(API ゲートウェイ) 部分です。
SPA の元ネタとなるコンテンツは (4) の S3 や CDN 経由で配布されるような想定です。初期化された SPA は、マイページとは別ページでも、マイページへの埋め込みでも、どちらでも実装は可能と考えています。また、認証は別サイトの認証基盤で行われます。この予約サイトとの認証連携は、SAML/OIDC などの SSO(Single Sign-On0や OAuth2.0 などを想定しています。
この SPA 上に予約コンテンツが表示されていて、公演内容をクリックしたり、座席の確保操作などをすると "API Manager" へそのイベントがすっ飛んでいきます。なぜ、ここで API のラッパーがいるのかというと、Kafka に直接連携するアプリをフロント側で実装するのが手間がかかるからです。他にも認可やセッションの制御を行うことが Kafkaで実装するのが、また厄介だから。ということで API ゲートウェイとなる "API Manager"という名前のラッパーアプリケーションを間に入れています。
この "API Manager" では、認可を行います。チケット予約のサイトなので「チケットの予約可否」とか「該当の公演へのアクセス可否」などを受け付けます。実は結構な処理です。ここは、SPAたるブラウザ上に暗号化/署名されたユーザ情報を持つなり、COOKIE ベースで"API Manager"に "Redis"などの高速ストレージにセッション情報を持って、ステートレスに実装します。ステートレスにしておかないと、スケールアウト対応が困難ですからね。
また、各公演のセッションを管理し、同時アクセス処理なども実装できます。処理がぶん回せれば、一つの公演に数千にアクセスさせることも可能でしょう。しかし、同時に大量のユーザがアクセスした時のことを想像ください。座席が表示されると共に、瞬時に埋まっていく様をエンドユーザが目の当たりにして、精神が正常にいられるでしょうか。ということで、仕組みにもよりますが、同時にアクセス可能なセッションを制御する機能も不可欠です。このセッションの情報も "Redis" で管理せざるを得ないでしょう。
2. イベントストリーム "Apache Kafka on Heroku"
イベント駆動の中心地、"Apache Kafka" はここに配置されます。ブラウザからのイベントは "API Manager" を経由して、このイベントストリームに全て入り込む仕組みにしています。
実際に構成を組む場合、CQRS(コマンドクエリ責務分離)に則って、クエリとコマンドに分けて、全てをイベントソーシングしないような実装も現実的な考え方です。
が、あえて、今回は完全なイベント駆動を実現したく、このような構成になっています。
3. リアルタイムの座席情報表示と仮予約トークンの発行
イベント駆動とは直接的に関係なさそうで、あるのがこの部分です。実は "Redis" にも Pub/Sub の機能があるのです(ババーン)
"リアルタイム座席情報" と "仮予約トークン発行" のアプリたちは、Redis を Subscribe して、取得された座席情報などを元にブラウザ上の SPAにリアルタイムで返す仕組みを想定しています。SPA とこれらのアプリは WebSocket などのロングポーリングで接続しっぱなしになっていて、更新があると(ほぼ)リアルタイムに情報が画面上へ反映される仕組みです。
実現方法を書くだけならば、なるほど、って感じでしょう。しかし、実装はここが一番難しいと考えています。WebSocket では SPA とアプリが接続しっぱなしの状況が続きます。アプリの起動時間を考慮しながら、自動的にスケールアウトするような仕組みを実装するには、かなりのチューニングとテストが必要でしょう。またスケールアウトしても、"Redis" の Pub/Sub で得られる情報と SPA とを紐付けて、どの Webアプリが、どの SPA に対して必要な情報を連携するか。なかなか重みがあります。
あと、ここで「仮予約トークン」というものを発行しているのは、後続の処理に対する負荷を多少削減しようという意図です。例えば、座席を確保したら、その座席に固有に割り当てられたユニークなIDを元に"JWT(JSON Web Token"などで暗号化(または署名)を行います。例えば「仮予約トークン発行」アプリが公開鍵で暗号化(署名)し、後続となる「本予約」が秘密鍵を持って復号化(署名の正当性保証)します。この仮予約トークンをブラウザ側のSPAに保持して、その後の処理を行うような仕組みです。
また、座席の仮予約に対しては、"Apache Kafka" が順序性を担保しつつ、"Redis" への仮予約を行います。トークン発行済みであれば、仮予約できているということにすれば排他制御も実現できます。
このようにして、本予約を行うときに仮予約トークンの内容を使って本予約を行うようにします。この方式であれば、ステートレスで安全な実装ができるのではという魂胆です。
また、仮予約の失効に関しても、トークン内に Expire の時間を設けたり、Redis のキーの有効期限を持つなりして強制失効の実装も可能なところも見逃せません。
4. 静的コンテンツの提供
直接、静的コンテンツへの URL があれば、CDN を経由して S3 のコンテつ情報を拾うようにすればよいです。各公演へのアクセスがあり、動的なコンテンツを返す必要がある場合は、リアルタイム座席表示のような WebScoket 化や、特定の静的コンテンツのURLを返す仕組みがあれば実装が容易と考えています。
5. さまざまな後続処理群
本予約や、決済処理など、コミット時の処理を全てこちら側に記しています。これらは完全に非同期で実装されていて、結果整合性を持って完結します。本予約が完了したら RDBMS たる "PostgreSQL" へコミットして予約が完了という仕組みです。
同様にクレジット決済であれば、クレカの決済サービスへと連携して非同期に決済を行います。ほかの決済サービスがあれば、該当の決済サービスとの処理をここに増やしていくことで対応が可能でしょう。
6. 外部連携の処理を行うプロセス群
"PostgreSQL" へコミットされた情報を、”Salesforce" CRM へ同期連携する "Heroku Connect" や、外部からの予約情報を反映させるような外部連携アプリサービスなどを準備します。
仮予約とのバッティングがあるため、通常のサイトとは別に提供する予約サイトを実現するには、考慮が必要です。結局、同じ仮予約サービスへ相乗りするか、外部サービス用に専用の座席を確保するか、等です。いわゆる優先席的な制度ですね。ここはビジネス要件による提供するサービスにあわせて、実装を検討します。
外部の決済サービスとの連携部分もこの部分です。決済処理サービス内で、直接外部の決済サービスと連携する処理も組み込むケースも多いでしょう。また、専用の EAI などを利用する場合もあります。そういった外部連携の機能をここで表現しています。
7. イベントの実行ログを保管するジャーナルサービス
このアーキテクチャは、"Apache Kafka" に全てのイベントが流れてくる仕組みとなっています。ですから、この "Apache Kafka" に入ってくるイベントを全てロギングすれば、全ジャーナル情報を保持することと同義です。SPA でページ遷移がないと画面上の JavaScript では取得できない行動もあります。しかし全てのイベントが "Apache Kafka" に流入してくるのであれば、それら全ての行動を記録することも可能です。
Pub/Sub の仕組みのおかげで全ての行動を記録可能なわけです。素敵。
8. アプリケーションの運用監視ツール群
ここはイベント駆動型アーキテクチャとは関係のない、Heroku でよく利用されているアプリケーション管理・監視ツールです。
ログ監視 - Papertrail
Heroku の出力するログは、1,500行までしかまき戻って閲覧することができません。また、出力されたログからアラートを発行することもできません。
そこで、ログ監視のアドオンです。この "Papertrail" は必要な機能を網羅的に持っていて、アーカイブ機能も持つ優れものです。地味に私もおうちのサーバのロガーとして使っています。
パフォーマンス監視 - Librato
Heroku の各コンポーネントから出力される統計情報を元に、アプリケーションやストレージのパフォーマンスを可視化するものです。
アプリケーション監視 - New Relic APM
オブザーバビリティで有名な New Relic です。あれの APM 部分を利用できるアドオンです。まぁそもそも Heroku だとインフラなどの管理はすべてSalesforceが実現しているので、取得可能なのがアプリケーションだけだからということですね。
他にも同様のツールは数多くあります。こういった管理系のツールは、みなさまのご希望とコストにあわせて選択くださいませ。
当イベント駆動型アーキテクチャのウリ
最後に、このアーキテクチャのウリを各所に記載しています。ご参考に。
ということで、思った以上に長くなりました。次回で多分最後、まとめの予定です。