JBoss Fuseを使い倒す その2:デザインパターン概要編
詳細化のパターン
ここからは、個々のルートパターンを詳細化したパターンです。EIPの書籍では、詳細化のパターンはだいたい次のように並べられています。まず、そのルートパターンにおける基本的/代表的なものから始まり、次第に応用的なパターンに進み、そして最後にそのルートパターンにアーキテクチャ的な展望を与えるパターンで締めくくる、といった順番です。
・メッセージチャネルのパターン システム間の通信手段をチャネルという形に概念化して扱うESBにおけるデータ通信(とくにメッセージングという非同期型通信)の特徴は、システム間の通信経路を「チャネル」という実体として扱う点にあります。通信経路を実体化することで、異なる通信スタイルのサポート(ポイントツーポイント、パブリッシュサブスクライブ)や、特定の経路に設計上の役割を持たせること(無効メッセージチャネル、配信不能チャネル)、サービスレベルの設定(配信保証)などが可能となります。
チャネルという用語は、Javaのメッセージング仕様であるJMSのキューまたはトピックに相当するものですが、他にも製品ベンダーによって様々な名前で呼ばれています。EIPではそれらをベンダーフリーに言い表す用語として、「チャネル」を採用しています。
パターン | 概要 | Camel組込 | |
---|---|---|---|
Point-to-Point Channel ポイントツーポイント・チャネル | 受信者が1つに限定された1対1のメッセージを送るために用いる(JMSにおけるキュー) | ○ | |
Publish-Subscribe Channel パブリッシュサブスクライブ・チャネル | メッセージを不特定多数へブロードキャストするために用いる(JMSにおけるトピック) | ○ | |
Datatype Channel データ型チャネル | メッセージの処理方法が分かるように、1つのチャネルを流れるメッセージのデータ型を統一する | ||
Invalid Message Channel 無効メッセージチャネル | データの内容に問題があって処理できないメッセージが転送される | ||
Dead Letter Channel 配信不能チャネル | 何らかの理由で宛先へ配信不能なメッセージが転送される(いわゆるDLQ) | ○ | |
Guaranteed Delivery 配信保証 | システム障害があっても確実にメッセージが配信されるように、メッセージの配信前後でメッセージを永続化する | ○ | |
Channel Adapter チャネルアダプタ | システム間統合に対応していないレガシーアプリケーションと接続するためのアダプタ | ||
Messaging Bridge メッセージングブリッジ | 複数のESB同士を接続するために、メッセージを複製する | ||
Message Bus メッセージバス | 複数のアプリケーションを、疎結合な方法で協調動作させる最適なアーキテクチャ | ○ |
まず、チャネルにはポイントツーポイントとパブリッシュサブスクライブの2種類があることを把握するのが、メッセージングを使いこなす上での第一ステップです。データ型チャネルやチャネルアダプタは、システム間統合ソリューションを設計する上での基本的なプラクティスと捉えればいいでしょう。
無効メッセージチャネル、配信不能チャネルの2パターンは、非同期型通信がベースのESBで例外処理を設計する上で必須の考え方です。同期型通信のRPCなどと違い、非同期型通信ではメッセージ処理中に例外が発生しても、それを即座に呼び出し側に返せません。そのため、まずリトライが可能であれば何度かリトライを繰り返し、その後に例外の種類に応じて特定のチャネルへメッセージを転送するのが、ESBにおける例外処理です。転送されたエラーメッセージの処理方法を決めるのは、システム間統合ソリューションの設計者の役割です。
メッセージングブリッジは、ESBを機能的にスケールアウトさせる場合や、既存のESB同士を相互運用したい場合に参考になるパターンです。
最後のメッセージバスは、チャネルの観点から見たシステム間統合ソリューションのあるべきアーキテクチャを示したものです。これがまさに、JBoss FuseなどのESBのアーキテクチャそのものであることに気付かれるでしょう。メッセージバスと、後のメッセージルーティングで登場するメッセージブローカを合わせると、ESBの見取り図のようなものが見えてきます。その意味で、EIPはESBが普及する以前に、ESBのあるべき姿を描いた書籍という読み方もできます。連載の第1回で、EIPが唯一生き残ったESBのデファクト・スタンダードであるという説明をしましたが、ある意味それは必然であることがここから伺えます。
メッセージ構築のパターン チャネルを通して通信するデータの単位を、ヘッダと本文からなるメッセージの形式で扱う
ここではメッセージそのものに焦点を当てて、その活用方法がパターンとして紹介されます。メッセージのヘッダを有効活用することで、メッセージングにまつわる様々な問題を解決できます。
パターン | 概要 | Camel組込 | |
---|---|---|---|
Command Message 命令メッセージ | アプリケーションの手続きを呼び出すため、命令をメッセージにして送信する | ||
Document Message 文書メッセージ | アプリケーション間でデータを転送するため、文書をメッセージにして送信する | ||
Event Message イベントメッセージ | イベントを通知するため、イベントをメッセージにして送信する | ○ | |
Request-Reply リクエストリプライ | 手続呼び出しのようなリクエストとリプライのやり取りを実現するため、リクエストとリプライのメッセージをそれぞれ別々のチャネルで送信する | ○ | |
Return Address 返信用アドレス | メッセージへの返信先チャネルをリクエスト側が指定するには、メッセージのヘッダに返信用アドレスを指定する | ○ | |
Correlation Identifier 相関識別子 | リクエストリプライにおいて、リクエストとリプライのメッセージ間の対応関係を識別するために、リプライメッセージにリクエストメッセージを一意に特定できる相関識別子を埋め込む | ○ | |
Message Sequence メッセージ順序 | データを複数のメッセージに分割し、それぞれに通し番号を付けて送信することで、メッセージングで大きなデータを送信できる | ||
Message Expiration メッセージ期限 | メッセージのヘッダに有効期限を埋め込むことで、古く無効になったメッセージを判定できるようにする | ||
Format Indicator 形式インジケータ | 同一チャネル上で将来的にメッセージのデータ形式に変更が発生するような場合は、データの中にどの形式が使われているかを明示できるようにデータ設計をする |
命令メッセージ、文書メッセージ、イベントメッセージは、あくまで設計上メッセージにどのような役割を与えるかであり、システム間統合ソリューションの実装時に、このように区分するわけではありません。リクエストリプライ型の通信をメッセージングで実現するには2つのチャネルが必要である、というのはメッセージングの基本です。JBoss Fuseでは、実際に2つのチャネルが使われていることを意識せずにリクエストリプライを実現できる仕組みが備わっています。
返信用アドレス、相関識別子、メッセージ順序、メッセージ期限、形式インジケータはそれぞれ、より詳細な要求をメッセージング上で実現しようとする際にヒントとなるパターンです。それ以外にも、メッセージヘッダを独自に活用することで、多種多様な要求に対応できるでしょう。
メッセージルーティングのパターン パイプ&フィルタにおいて複雑なメッセージ処理を実現するには、メッセージをルーティングするフィルタを導入する
パイプ&フィルタアーキテクチャの「フィルタ」に相当するメッセージルーティングは、システム間統合ソリューションにおける中心的なロジックとなる部分です。続くメッセージ変換も同様にフィルタに相当しますが、メッセージルーティングではメッセージそのものに変更を加えることなく、あくまでメッセージをどのように配送するかということが中心のテーマとなります。
パターン | 概要 | Camel組込 | |
---|---|---|---|
Content-Based Router コンテンツベースルータ | 内容(コンテンツ)に基づいて、メッセージを異なる宛先に振り分ける | ○ | |
Message Filter メッセージフィルタ | メッセージを、一定の条件によってフィルタリングする | ○ | |
Dynamic Router 動的ルータ | 実行時に外部から設定変更可能なルータによって、メッセージの宛先を動的に切り替える | ○ | |
Recipient List 受信者リスト | メッセージを複数の宛先に一斉に送信する。宛先のリストは動的に変更できる | ○ | |
Splitter 分配器 | 1つのメッセージを分割して、それぞれを異なる宛先に送信する | ○ | |
Aggregator 集約器 | 複数のメッセージを1つに集約する | ○ | |
Resequencer 再配列器 | 順不同で流れてくる一連のメッセージを、正しい順序に並べ替える | ○ | |
Composed Message Processor 組立式メッセージプロセッサ | 分配器、コンテンツベースルータ、集約器を組み合わせることで、メッセージを分割して部分ごとに並列処理し、最後に再集約するという複雑なメッセージフローを実現する | ○ | |
Scatter-Gather 分散・回収 | 複数の宛先にメッセージを送信し、その結果をまとめて受信したい場合に、受信者リストまたはパブリッシュサブスクライブ・チャネルを用いてメッセージを一斉配信し、結果を集約器でまとめて受け取る | ○ | |
Routing Slip 回覧票 | メッセージごとに処理ステップ(宛先)が変わるようなメッセージフローを実現するために、各メッセージに処理ステップの順番を示した回覧票を持たせ、それに基づいてプロセッサからプロセッサへメッセージをルーティングする | ○ | |
Process Manager プロセスマネージャ | 回覧票よりも複雑で汎用的なメッセージフローの管理が必要な場合は、中央集権的なプロセスマネージャを導入し、そこでフローを一元管理する | ||
Message Broker メッセージブローカ | エンドポイント同士を疎結合にし、ルーティングを中央集権的に管理するアーキテクチャを追究すると、ハブ&スポーク型のメッセージブローカ・アーキテクチャになる |
コンテンツベースルータ、メッセージフィルタ、受信者リスト、分配器、集約器、再配列器の6つは、メッセージルーティングの基本ブロックとなるパターンです。ほとんどのルーティングに関する要求は、この6つの組み合わせで実現できるでしょう。メッセージフィルタは、メッセージのコンテンツを条件に照らして、そのメッセージを次の宛先に通すかまたは破棄する(nullチャネルに送る)特殊なコンテンツベースルータと見ることもできます。
動的ルータは、上記の基本パターンに比べて少し特異なパターンです。このパターンは、実行時に外部から設定変更可能なインタフェースを作って、動的にルーティングを制御できる可能性を示しています。動的ルータはルーティングを外部から制御できるという特徴から、最後に登場するシステム管理のパターンと関連が深く、一緒に用いられることの多いパターンです。
組立式メッセージプロセッサと分散・回収は、上記の基本パターンを組み合わせてより複雑なルーティングを実現した例です。2、3の基本ルーティングパターンを組み合わせるだけで、かなり複雑で興味深い働きをするルーティングを設計できることが分かります。
メッセージフローをさらに動的に、柔軟にカスタマイズできるようにしようと突き詰めていくと、回覧票やプロセスマネージャのような設計にたどり着きます。ここまで来ると、メッセージルーティングはワークフローエンジンやBPMエンジンに近づいていきます。
最後のメッセージブローカは、先ほどメッセージチャネルのパターンでメッセージバスと共に触れたように、ESBの見取り図とでも言えるようなアーキテクチャパターンです。ESBにおいては、各アプリケーションはESBとだけ通信すればよく、アプリケーション間は疎結合に保たれます。アプリケーション間の連携は、ESBの中のルーティングによって一元的に管理されます。
Camel独自のパターン
オリジナルのEIPのパターンに加えて、Camelにはコミュニティによって集められた新たなルーティングパターンも追加されています。
Throttler(調節弁) | メッセージの流量に制限をかけて、特定のエンドポイントが過負荷で性能を落とさないようにしたり、外部サービスとのSLAを順守したりする |
---|---|
Sampling(サンプリング) | サンプリングによる調整弁の一種。一定の間隔でメッセージを抽出することで、流量を調節する |
Delayer(遅延器) | メッセージの配送をわざと遅延させる |
Load Balancer(ロードバランサ) | 様々なポリシーによるメッセージのロードバランシングを実現する |
Multicast(マルチキャスト) | 受信者リストの一種。マルチキャストでは、宛先のリストは設計時に固定され、動的に変更できない |
Loop(ループ) | 特定のルーティングを一定回数繰り返す |