Correlation Identifier †
サマリ †
メッセージングで非同期になると、リクエストとレスポンスを紐付けるのも簡単じゃないですよ。紐付けるには、レスポンスメッセージにリクエストを特定できるIDを持たせましょう。
詳細 †
返信を受け取った要求側は、その返信がどの要求に対するものかをどうやって知ればよいか?
- MessagingはRemote Procedure Invocationと違い非同期なので、呼び出しとその結果の受け取りとには時間差がある。呼び出し側で要求とその結果とを紐付けることは難しい。
- いくつかのアプローチが考えられる。
- 1度に1つずつしかメッセージを送らない。 -> しかし、スループットが非常に遅くなってしまう。
- メッセージを送った順番に返信も帰ってくるものと想定する。 -> メッセージングではそんなに甘い仮定は成り立たない。(Resequencer参照)
- 一方通行で返信が必要ないように設計する。 -> メッセージングの適用範囲が非常に限定されてしまう。
- 必要なのは、返信メッセージが要求メッセージへのポインタを持つことだ。メッセージに一意なIDを割り当てて、それを他のメッセージにキーとして持たせることはできる。
返信メッセージそれぞれに「相関ID(Correlation Identifier)」を持たせ、それによって対応する要求メッセージを一意に特定する。
- 相関IDには6つの構成要素がある。
- 1. 要求者(Requester) 2. 返信者(Replier) 3. 要求(Request) 4. 返信(Reply) 5. 要求ID(Request ID) 6. 相関ID(Correlation ID)
- 相関IDの仕組み:要求者が要求メッセージを生成するとき、要求IDを割り当てる。返信者が要求メッセージを受け取ると、その要求IDを保存し、返信メッセージを作成する際にそれを相関IDに割り当てる。
- 要求者と返信者は、要求ID、相関IDの名前や型、メッセージ形式(XML等)などの詳細について合意しておく必要がある。
- このパターンは、POSA2のAsynchronous Completion Tokenパターンのより単純化されたメッセージング固有のバージョンである。要求者がInitiator、返信者がService、要求者の中の返信を処理する部分がCompletion Handler、相関IDがAsynchronous Completion Tokenに対応する。
- 相関ID(要求IDも)は通常、メッセージのヘッダに持たせる。IDは要求者が返信者へ伝えようとするコマンドまたはデータの一部ではないから。
- このパターンのキモは、返信メッセージに対応する要求を特定するためのトークンを持たせること。それには、いくつかのアプローチがある。
- 最もシンプルな方法は、要求メッセージに一意なID(メッセージID)を割り振って、それをそのまま返信の相関IDにすること。しかし、どんなビジネスタスクを実行している過程でその要求をしたのかを思い出すことが要求者にとっては重要で、要求メッセージそのものを特定しただけでは役に立たないことが多い。
- ビジネスタスクはおそらくそれ自身が一意なビジネス上の識別子(注文番号、等)を持っているはずで、それを相関IDに使う方法もある。この方法だと、返信を受け取ったら要求メッセージに遡らずに完了したいビジネスタスクを直接再開できる。この場合は、ビルトインのメッセージIDや相関IDのプロパティを使わず、独自のビジネスオブジェクトID(=ビジネス上の識別子)をプロパティに設定することになる。
- 上記2つの折衷案として、マップで要求メッセージIDとビジネスオブジェクトIDとを管理する方法もある。このアプローチは、返信側の実装を自由にコントロールできない状況で極めて有効。
- メッセージIDと相関IDとを別々のプロパティにすることで、要求/返信メッセージをチェイン状にすることも可能。返信メッセージを更に要求メッセージとして使い、その返信メッセージを更に要求メッセージとして使う・・・といった場合。
- メッセージチェイニングをしたいのは、たいていオリジナルの要求メッセージへ遡りたいだけのことが多い。その場合は、すべての返信に同じ相関IDを割り振ればよい。
他のパターンとの関係 †
例:JMSのCorrelation-IDプロパティ †
- JMSメッセージには、定義済みの相関ID、JMSCorrelationIDが用意されている。JMSMessageIDと一緒に使う。
例:.NETのCorrelationId?プロパティ †
- .NETメッセージにはCorrelationId?プロパティがあって、PeekByCorrelationId?(string)またはReceiveByCorrelationId?(string)メソッドで特定の相関IDを持ったメッセージだけを取得することができる。
例:Webサービスのリクエスト/レスポンス †
担当者のつぶやき †