JBoss Fuseを使い倒す その2:デザインパターン概要編
はじめに
これまでの記事では、JBoss Fuseの基本的な使い方や設定方法を紹介してきました。しかし、いざJBoss Fuseを使って本格的なシステム間統合ソリューションを設計・実装しようとなると、現実のシステム間統合のシナリオで求められる、より実践的な設計ノウハウが必要となります。こうした実践的なノウハウ集、つまりシステム間統合のデザインパターンを知り、必要に応じてそれらを適用できるようにしておくことが、JBoss Fuseの導入を成功させる上で非常に重要です。
例えば、以下のようなシステム間統合の設計課題を考えてみてください。
- リクエスト/リプライ型の非同期メッセージングを行いたいときに、どのようにリクエストとリプライのメッセージをひも付ければいいか
- 非同期メッセージの処理中に発生しうるエラーに対して、どのような例外処理を設計すればいいか
- 1つのメッセージでは送りきれないような大きなデータを転送したい場合に、どういった設計アプローチがあるか
- 構築したシステム間統合ソリューションの、運用時におけるシステム監視・管理をどのように設計すればよいか
こうした実践的な設計課題に対して、先人達がたどり着いた答えをまとめたものが、これまでもたびたび登場した「エンタープライズ統合パターン(Enterprise Integration Patterns、以下、EIP)」です。本連載の締めくくりに、EIPの概要と、EIPをJBoss Fuse上でどのように活用できるかについて、2回に分けて紹介していきます。今回は、EIPの概要編です。
エンタープライズ統合パターンとは
改めて紹介すると、EIPは2003年に書籍『Enterprise Integration Patterns』(Gregor Hohpe、Bobby Woolf著)でまとめられたパターン集です。原著の出版からおよそ12年も経った2015年になっても、残念ながら日本語訳は出版されていません。本書は、ESBやSOAに携わる技術者必携の書籍ですので、洋書ではありますが、手元に一冊置いておくことをお薦めします。
パターンカタログと各パターンの要約、およびケーススタディの3章(「Interlude:...」の章)を含む書籍の一部は、EIPの公式サイトでも参照できます。
EIPを理解する上で注目すべき特徴の1つは、それがパターン「言語」を構成していることです。いわゆるGoF(Gang of Four)デザインパターンのような、パターン間につながりの乏しい単なるパターンカタログではありません。システム間統合のソリューション全体を扱う大局的なパターンに始まり、そこから部分・全体の関係を保ちつつ段階的に詳細なパターンへと細分化されていく、という構造を持ちます。さらに、同じ詳細レベルの個々のパターン間でも様々な関連が張り巡らされており、1つのパターンの適用が別のパターンへと派生していくといった、パターンとして望ましいとされる有機的な言語の特徴を持ちます。
基本的なシステム間統合スタイル
EIPはまず、エンタープライズにおけるシステム間の統合アプローチを、大きく次の4つのスタイルにパターンとして分類します。
パターン | 概要 | |
---|---|---|
File Transfer ファイル転送 | ファイルを介してシステム間の通信を行う | |
Shared Database 共有データベース | 共通のデータベースを参照・書き込みすることで、システム間のデータをやり取りする | |
Remote Procedure Invocation リモート手続呼出 | Webサービス(SOAP、REST)のような同期型のRPCによって、システム間の通信を行う | |
Messaging メッセージング | JMSのような非同期型のチャネルを介して、システム間の通信を行う |
ファイル転送や共有データベースは、昔から行われてきたよくあるシステム間統合のスタイルと言えるでしょう。これらのスタイルの特徴は、導入の技術的敷居が低いことです。その一方で、ファイル転送にはバッチ処理により必然的にタイムラグが発生する、共有データベースにはデータの共有のみで機能や処理の共有はできない、といった様々な問題があります。
そういった問題に対処できるスタイルとしてリモート手続呼出とメッセージングがあります。どちらもデータではなく機能・処理を統合するアプローチですが、それが同期型か非同期型かでリモート手続呼出とメッセージングに分かれます。
EIPとESB
EIPの書籍では、メッセージングを最も洗練された統合スタイルであるとしており、以降のパターンは全てこのメッセージングを深く掘り下げたものとして説明されています。しかしESB(Enterprise Service Bus)が普及した現在、筆者は必ずしもEIPを「メッセージング」に限定したパターンと捉える必要はないと考えます。
EIPが出版された2003年当時、システム間統合の製品としてはMOM(Message-Oriented Middleware)やEAI(Enterprise Application Integration)といったカテゴリが主流でした。EIPを体現したミドルウェアとでも言えるESBの概念は、まだほとんど普及していませんでした。
実際のところJBoss Fuseを含むESBでは、一般にどの統合スタイルを取るかという問題は、外部システムとESBとの接続点であるエンドポイントにおいて抽象化されるものであり、その通信のメッセージ交換パターン(Message Exchange Pattern:MEP)さえ意識しておけば、基本的にはEIPのどのパターンも適用可能になります。したがって本記事では、あえてEIPをメッセージングに限定せずに説明していきます。
システム間統合のパターン「言語」
EIPのパターン言語が始まるのは、ここからです。EIPのパターン言語は、トップダウンの整然とした階層構造をしています(図2)。
この図から分かるように、EIPはシステム間統合のソリューション(=ESB/メッセージングシステム)をメッセージチャネル、メッセージ、パイプ&フィルタ、メッセージルータ、メッセージ変換、メッセージエンドポイントという6つの概念に細分化します。本連載の読者の皆さんは、Apache Camelのアーキテクチャが、この構成にそのまま基づいていることに気づかれたでしょう。
この6つの概念にまつわる基本的な問題と解決策、および検討事項がまず大局的な「ルートパターン」として定義されます。
パターン | 概要 | |
---|---|---|
Message Channel メッセージチャネル | システム間の通信手段を、チャネルという形に概念化して扱う | |
Message メッセージ | チャネルを介して通信するデータの単位を、ヘッダと本文からなるメッセージの形式で扱う | |
Pipes and Filters パイプ&フィルタ | システム間統合の基本的なアーキテクチャの考え方。UNIXのようにパイプ(チャネル)とフィルタ(プロセッサ)でソリューションを構築する | |
Message Router メッセージルータ | パイプ&フィルタにおいて複雑なメッセージ処理を実現するには、メッセージをルーティングするフィルタを導入する | |
Message Translator メッセージ変換 | システム間のデータ形式の違いを吸収するために、メッセージを変換するフィルタを導入する | |
Message Endpoint メッセージエンドポイント | ESBが外部システムと接続する部分を、エンドポイントという形で抽象化する |
EIPのパターン言語は、これらのルートパターンがまずシステム間統合ソリューションの大枠の問題についての解決策を示した上で、個々のルートパターンが内包する詳細な技術的課題や特殊なケースへの対応、さらに派生する設計問題などを、ルートパターンの元で深堀りする構成になっています。
さらに、システム間統合ソリューションの監視・管理に関するパターンがこの体系に加えられて、全体としてのEIPが完成します。ただし監視・管理に関するパターンは、システム間統合ソリューションの本体からすれば付随的であるためか、ルートパターンには表されていません。
なお、EIPではメッセージが図3のように独特なアイコンで表現されますが、これはXMLのように、ルート要素があってそこから子要素が階層的にぶら下がる半構造データを表現していると理解すればいいでしょう。
詳細化のパターン
ここからは、個々のルートパターンを詳細化したパターンです。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(ループ) | 特定のルーティングを一定回数繰り返す |
メッセージ変換のパターン システム間のデータ形式の違いを吸収するために、メッセージを変換するフィルタを導入する
メッセージルーティングと並ぶ、システム間統合ソリューションにおける中心的なロジックが、メッセージの変換です。
パターン | 概要 | Camel組込 | |
---|---|---|---|
Envelope Wrapper エンベロープラッパー | 生のアプリケーションデータをESB上で扱うために、データにエンベロープを被せてメッセージ形式(ヘッダと本文が分かれている)にする | ||
Content Enricher コンテンツ付加器 | 他のシステムと通信するための情報が不足しているメッセージに、外部のデータソースからデータを取得して補完する。 | ○ | |
Content Filter コンテンツフィルタ | メッセージから不要なデータを取り除く | ○ | |
Claim Check 荷物預かり | コンテンツフィルタで削除できない重要だがサイズの大きいデータを、ESBで取り扱いたい場合は、いったんそのデータをデータストアに永続化し、メッセージにはそのキー(荷物預かり票)を持たせる。データが必要になったら、コンテンツ付加器を用いてデータを復元する | ○ | |
Normalizer 正規化器 | コンテンツベースルータとメッセージ変換を組み合わせ、様々な形式のメッセージを、意味を変えずに標準の形式に変換する。 | ○ | |
Canonical Data Model 標準データモデル | データ形式の標準化戦略についての考え方。メッセージ変換によって、システム間統合ソリューション内部では標準のデータモデルのみ流れるように設計することで、メッセージ変換の組み合わせ爆発を防ぐ |
あらゆるデータをESB上で扱う際に、エンベロープラッパーの考え方が重要です。組み込みでのサポートこそ謳われてないものの、Camelでは全ての入出力データは自動的にExchangeオブジェクトに被せられて扱われるため、標準でエンベロープラッパーに対応していると言えます。
メッセージ変換の基本はメッセージのデータを増やすか減らすかですが、それぞれがコンテンツ付加器とコンテンツフィルタに対応しています。コンテンツフィルタと、メッセージルーティングのパターンであるメッセージフィルタの違いは、前者はメッセージの中身の一部分をフィルタリングするのに対して、後者はメッセージそのものをフィルタリングするという点です。これがメッセージ変換とルーティングとの違いを端的に表しています。
メッセージ構築のメッセージ順序パターンと並び、荷物預かりはESB上で大きなサイズのデータを扱う際の設計のヒントになります。まさしく空港で飛行機に乗る前に大きな荷物を預けるイメージで、アイデアとして純粋に興味深いパターンでもあります。荷物預かりは大きなデータを扱う場合だけでなく、特定のエンドポイントにそのまま公開したくない情報がある際の、情報隠蔽の手段としても利用できます。
最後の標準データモデルは、メッセージ変換をアーキテクチャの中に取り入れて、どうやってデータモデルの標準化を行うかに関するパターンです。他のメッセージ変換パターンより少し高い視点の話題を扱っています。企業内でのデータモデルの標準化というのは誰もが夢見るテーマではありますが、実現がなかなか難しいのもまた事実です。ESBが標準データモデルの実現を多少容易にしてくれるのは間違いありませんが、他のアーキテクチャレベルのパターン、メッセージバスやメッセージブローカとは違い、ESBを導入しただけで必ずしも実現できるパターンではありません。
Camel独自のパターン
メッセージ変換については、Camelは以下のパターンを新たにEIPに追加しています。
Sort(ソート) | メッセージの本文をソートする |
---|---|
Validate(妥当性検証) | メッセージのヘッダおよび本文のデータを妥当性検証する |
メッセージエンドポイントのパターン ESBが外部システムと接続する部分を、エンドポイントという形で抽象化する
これまでは通信経路であるチャネル、データであるメッセージ、そしてそのメッセージの配送(ルーティング)や編集(変換)に焦点が当てられてきました。ここでは、ESBの最後の重要箇所である、チャネルを通して外部システムと接続する部分(エンドポイント)に焦点が当てられ、様々な設計上の検討事項がパターンとして議論されます。
エンドポイントは、メッセージのコンシューマとプロデューサのどちらも含んでいます。しかし、メッセージを送信する場合に比べ、受信する場合の方が様々な設計上の工夫が必要であるため、コンシューマに関するパターンの比重が多くなっています。
パターン | 概要 | Camel組込 | |
---|---|---|---|
Messaging Gateway メッセージングゲートウェイ | アプリケーション側でESBとの通信層を設計する場合は、メッセージングのAPIをゲートウェイにカプセル化し、アプリケーションロジックとメッセージングのロジックを切り分ける | ○ | |
Messaging Mapper メッセージングマッパー | アプリケーションのドメインモデルとメッセージング層を完全に分離するには、DBアクセスにおけるORマッピングのような仕組みをメッセージングに導入する | ○ | |
Transactional Client トランザクションクライアント | ESBではクライアント側(メッセージ送信者または受信者)がトランザクション管理を主導する | ○ | |
Polling Consumer ポーリングコンシューマ | メッセージの受信方法の一種。一定間隔で明示的にポーリングして、メッセージの到着を確認する | ○ | |
Event-Driven Consumer イベント駆動コンシューマ | メッセージの受信方法の一種。リスナーを登録して、メッセージが到着したら自動的に処理が実行される。 | ○ | |
Competing Consumers 競合型コンシューマ | 1つのチャネルに対して競合する複数のコンシューマを走らせることで、メッセージを並列処理する | ○ | |
Message Dispatcher メッセージディスパッチャ | 競合型コンシューマと対照的に、メッセージ並列処理を調整するディスパッチャにまずメッセージを受信させ、ディスパッチャが適切なルールに基づき処理を後続の並列メッセージ処理プロセスに振り分ける | ○ | |
Selective Consumer 選択型コンシューマ | 一定の条件で選択的にメッセージを受信したい場合は、チャネル側のフィルタリング機能を使うか、メッセージ受信後にメッセージフィルタを用いて必要なメッセージだけを残すか、2通りの方法がある | ○ | |
Durable Subscriber 永続的サブスクライバ | サブスクライバがオフラインのときにチャネルに到着したメッセージも取りこぼしたくない場合は、永続的サブスクライバの設定を有効にする | ○ | |
Idempotent Receiver 冪(べき)等レシーバ | 同一メッセージの重複受信に対応するには、重複を検知して明示的に排除する仕組みを作るか、同一メッセージを複数回処理しても問題が起こらないようにシステムを設計する | ○ | |
Service Activator サービスアクティベータ | リモート手続呼出型のサービスにメッセージングのAPIを付加したい場合は、リクエストリプライ型のメッセージングをリモート手続呼出に変換する層(サービスアクティベータ)を導入する | ○ |
メッセージングゲートウェイとメッセージングマッパーは、エンタープライズアプリケーションアーキテクチャパターンにおけるゲートウェイ(Gateway)やデータマッパー(Data Mapper)のパターンにそれぞれ対応するもので、アプリケーションにメッセージングによる通信層を設計する際のベストプラクティスです。
ポーリングコンシューマ、イベント駆動コンシューマ、競合型コンシューマ、メッセージディスパッチャ、選択型コンシューマ、永続的サブスクライバ、冪等レシーバは、いずれもメッセージのコンシューマに関するパターンです。
ESBにおいては、エンドポイントの種類によってポーリングコンシューマとイベント駆動コンシューマのどちらを採用すべきか決まります。例えばデータベースのようにイベント駆動型のAPIを提供しないエンドポイントでは、ポーリングコンシューマが選択肢になります。逆にJMSやMDB(Message-Driven Bean)では、イベント駆動コンシューマを採用するのが自然でしょう。
競合型コンシューマとメッセージディスパッチャの2つは、ESBのクラスタリング環境を設計する際のヒントとなるパターンです。永続的サブスクライバと冪等レシーバは、ESBの耐障害性や重複排除といった要求を実現する上で必須の仕組みです。
システム管理のパターン
エンタープライズシステムは単に開発すれば終わりではなく、本番運用においてトラブルを検知・回避・復旧できるように、稼働状況を継続的に監視・管理する仕組みを構築するところまでがセットです。それは、ESBにおいても同様です。
システム間の統合を行うESBは、通常のアプリケーションとは異なる特徴を持ちますので、その運用・監視のアプローチにも独自のノウハウがあります。ここでは、そうしたESBに固有の運用・監視パターンがまとめられます。
パターン | 概要 | Camel組込 | |
---|---|---|---|
Control Bus 制御バス | ESBを監視・管理する仕組みを作るには、それ自身をESB上のシステム間統合ソリューションとして構築するのが有効である。ただし、監視・管理用のメッセージチャネルは本体とは別に用意する | ○ | |
Detour 迂回路 | コンテンツベースルータを制御バスによって制御することで、システム管理目的でメッセージフローを一時的に迂回させるような仕組みを実現できる。例えば、あるルートのメッセージを一時的に検証、テスト、デバッグするなどの用途に使う | ○ | |
Wire Tap 盗聴器 | ESBを流れるメッセージを途中で監視したい場合は、本来の宛先と監視用の宛先の2つを持つ受信者リストを導入して、本来のメッセージフローを邪魔せずにメッセージを監視する | ○ | |
Message History メッセージ履歴 | メッセージのルーティング履歴をメッセージ自身に記録していくことで、メッセージフローのデバッグや分析に活用できる | ○ | |
Message Store メッセージストア | ESB上のシステム間統合ソリューションに対して何らかのレポートを作成したい場合に、レポーティング用のチャネルを用意して、システム中の様々な場所を流れるメッセージを一箇所に記録する。 | ||
Smart Proxy スマートプロキシ | 返信用アドレスを使って返信先を指定しているリクエストリプライメッセージングの間にプロキシを挟みたい場合、プロキシ側でいったんメッセージの返信用アドレスをプロキシ自身に書き換える。プロキシに戻ってきたリプライメッセージは、ルータを使って元の返信用アドレスに送り返す | ||
Test Message テストメッセージ | ESBの健康状態を監視するために、本番稼働中のシステムに定期的にテストメッセージを流して内部動作を点検する | ||
Channel Purger チャネル消去器 | テストや本番稼働中において、チャネルに残ったゴミメッセージが動作に影響を及ぼさないように、チャネルのメッセージを一掃する仕組み |
システム間統合ソリューションで何より特徴的なのは、そのシステム管理もメッセージングをベースに構築するのが有効だという点です。それを端的に表したのが制御バスパターンです。EIPにおけるシステム管理の考え方は、この制御バスが出発点になります。
迂回路、盗聴器、スマートプロキシは、ルーティングの中にシステム管理用の部品を埋め込むアイデアを示したものです。特に盗聴器は非常にポピュラーなパターンで、Camelを使ったシステムでもよく使われます。
メッセージ履歴とメッセージストアは、システム間統合ソリューションの動作を分析・レポーティングするのに有効です。メッセージストアは、自分でその仕組みを構築しなければいけませんが、メッセージ履歴はCamelでは標準でサポートされており、何もしないでもすぐに利用できます。
最後に、メッセージングに固有のテストやデバッギングのノウハウ、テストメッセージとチャネル消去器も把握しておく必要があります。システム同士を統合するシステム間統合ソリューションでは、当然ながら単体テストよりも統合テスト以降がもっとも重要なテストフェーズになります。
特にテストメッセージが示すように、開発時だけでなく本番稼動時にも定期的にテストメッセージを流してシステムの健康状態を確認する、いわゆるアクティブモニタリングと呼ばれる手法がシステム間統合ソリューションでは非常に有効です。DevOpsが注目を集めている昨今、改めて本番環境にテストを組み込むというアプローチが見直されてもよいのかもしれません。
Camel独自のパターン
Camelは以下のパターンをシステム管理のパターンに追加しています。
Log(ログ) | メッセージをロギングする |
---|
おわりに
非常に駆け足でしたが、EIPの全体像を紹介しました。本記事は、あくまでEIPを実際のシステム間統合に適用するきっかけを作るための、最初の手引きに過ぎません。パターンの真の価値は、単に頻出する問題とその解決策がセットになっていることだけではなく、解決策に付随する様々なトレードオフや選択肢、設計上の検討事項などがエキスパートの手によって文書化されていることにあります。本記事で興味を引くパターンを見つけたら、ぜひ書籍を手にとってその詳細な議論にも触れてください。
次回はEIPをいくつかピックアップして、JBoss Fuse上で実際にどのようにパターンを適用できるかを紹介したいと思います。