読者の皆様へ: 皆様のご要望にお応えするべく、ノイズを削減する機能セットを開発しました。皆様が関心をお持ちのトピックを、EメールとWeb通知で受け取ることができます。新機能をぜひお試しください。
マイクロサービスシステムにおける同期型の要求-応答通信は、場合によっては非常に複雑なものになるが、幸いにもイベントベースのアーキテクチャがこれを回避する手段になる — QCon London 2018でのプレゼンテーションで、Yaroslav Tkachenko氏はこのように主張し、イベントアーキテクチャでの自身の経験から、このアーキテクチャでシステムを構築する上でアクタを利用する方法について説明した。
DemonwareのシニアソフトウェアエンジニアであるTkachenko氏が講演の冒頭に強調したのは、ネットワーク上の同期要求はローカルの場合と同じようには実行できない、という点である。ネットワーク通信に関連して発生する、克服困難な課題が山のようにあるからだ。マイクロサービスや分散システムの開発経験が不足している場合はなおさらだ。イベント駆動アーキテクチャは、氏にとって、発生の予想される問題を解決するための、より直接的なアプローチなのだ。
Demonwareには巨大なアプリケーションモノリスが依然として存在するが、独立したサービスへの移行が徐々に進んでいる。同社ではかねてから同期型の要求-応答通信を多用してきたが、現在では非同期な通信への移行に取り組むと同時に、サービス間でのドメインイベントの使用を決定している。
Demonwareの大部分のサービスはドメイン駆動設計(DDD)とヘキサゴナルアーキテクチャに基づいており、メッセージトランスポート層としてKafkaを使用している。受信したイベントは、ビジネスロジックコアに送信される前に、イベントアダプタのコマンドに変換されるこれに対応して、サービスが生成したイベントが、“ファイア・アンド・フォーゲット”または高々1回のデリバリを保証された形式でKafkaに追加され、リモートあるいはローカルのイベントストアにバックアップされる。
要約すると、Demonwareの使用するイベントフレームワークは次のようなものだ。
- コールバックを使用した、デコレータ駆動のイベントコンシューマ
- 信頼できるプロデューサ
- 非ブロックIO
- トランスポート用のApache Kafka
この設計を単純化するために、メッセージパッシングをネイティブにサポートするアクタを、コンシューマとプロデューサの両方で使用している。ここで言うアクタとは、簡単には次のようなものだ。
- 非同期かつ非ブロックのメッセージを使って相互通信する
- 自身の状態を管理する
- メッセージへの応答時には、子アクタを生成して他のアクタにメッセージを送信し、子アクタや自分自身を停止することができる
アクタモデルを使い始めたTkachenko氏は、システム全体がメッセージングあるいはイベント駆動型のシステムであることに気が付いた。この分野のパターンに関して氏は、エンタープライズインテグレーションパターンに関する書籍と、Vaughn Vemon氏の著書である“Reactive Messaging Patterns with the Actor Model”を推奨している。
アクタモデルに基づく実装としてTkachenko氏は、同社のBench Accountingを紹介した。このシステムは大規模なJavaエンタープライズモノリスであったのを、一連のScalaマイクロサービスとAkkaを使用したアクタに変更したものだ。このシステムの核となるのは、メッセージキューを処理するActiveMQとインテグレーションフレームワークのApache Camel、現在はAlpakkaにリプレースされて非推奨になった公式Akkaライブラリのakka-camelである。
この実装における典型的なイベントリスナは、akka-camelがキューからメッセージを取得し、デシリアライズして変換し、必要な処理を行なった上でアクタに送信する。送信側も同様で、アクタがakka-camelを使用してシリアライズ他の処理を行なった後に、メッセージをキューに送信する。
要約すると、この実装では次のようなイベントフレームワークを使用している。
- Apache Camelを使用した、アクタベースのコンシューマとプロデューサ
- ACKを備えたプロデューサ
- 非ブロックIO
- トランスポートとしてActiveMQ
アクタを使った開発を通じて、Tkachenko氏は次のような教訓を得た。
- セマンティクスの重要性。ニュートラルなメッセージパッシングには大きなメリットがある。
- デフォルトとしての非同期通信とロケーションに関する透過性は、アクタのサービスバウンダリ間の移動を容易にする。
- より高度なメリットとしては、スーパバイザ階層、“クラッシュさせる(let it crash)”発想、高度な並列性などがある。
その上で氏は、次のように推奨する。
- ドメイン駆動設計(DDD)と書籍“Enterprise Integration Patterns”が役に立つ
- 自身のドメイン空間を理解した上で、イベント、コマンド、ドキュメントの中から必要なコンセプトを選択せよ
- 可能性のある障害はすべて明示的に処理せよ — それらはいずれ発生する
- 必要でない限り、“高々1回”のセマンティクスは避けること — それは非常に高価である
- メッセージ形式とスキーマは極めて重要だ。氏の推奨はProtobufやAvroにようなバイナリ形式だが、JSONを使用する場合は、早期にスキーマ戦略をデザインしておくことが重要である
氏が経験した課題は次のようなものだ。
- 同期的なパラダイムから非同期への移行は難しく、時間を要する。
- 結合性の高さは後々問題となる。イベントを使って結合を回避し、コマンドの使用は最小限に抑えること。
- 書き込み処理をイベントベース通信で実装するのは容易だが、読み込み処理は非常に難しい。DB正規化、インメモリデータ構造、あるいはストリーム処理などが一般的な手法である。
- メッセージブローカクラスタの管理は、今はまだ重要な問題ではない。
アクタを利用すべきかどうかはニーズ次第だ。非同期かつ非ブロックなイベントフレームワークの構築はさまざまな言語で構築可能だが、本質的に非同期かつメッセージベースであるアクタは、必要な場合にはアドバンテージとなる。
カンファレンスの主要なプレゼンテーションは録画されており、今後数ヶ月にわたってInfoQで公開される予定である。次回のQConカンファレンスであるQCon.aiは、AIとマシンラーニングに重点を置くもので、2018年4月9~11日にサンフランシスコで開催される。QCon London 2019は、2019年3月4~8日に開催が予定されている。
この記事を評価
- 編集者評
- 編集長アクション