EIP / Message Channel


Message Channel

一言要約

メッセージングシステムではむやみに情報を飛ばしまくってるわけではなく、扱うデータの種類ごとにMessage Channelを設けて扱い分けている。

要約

ある企業がMessagingを使って通信する必要がある二つの独立したアプリケーションを持っている。

アプリケーションはどうやってメッセージングを使ってもう一つと通信するのか?

アプリケーション群はメッセージングシステムを持っていると、どんなアプリケーションでも好きな時に他のアプリケーションと通信できると思いがちだが、メッセージングシステムは魔法のようには繋がらない。

アプリケーションはランダムに情報をメッセージングシステムへ投げたり取得したりするわけではなく、送りたい情報が何かを知っており受け取る側も利用したいものだけを扱う。

Message Channelを使ってアプリケーションを接続すると、チャネルに対して情報を書き込みチャネルから情報を読み込む。

アプリケーションはメッセージングシステムにただ情報を投げ飛ばすのではなく、特定のMessage Channelに対して情報を付与し、受け取る際もランダムではなく特定のMessage Channelから情報を受け取る。

送信側のアプリケーションは受信側を知る必要はないが、受信側のアプリケーションがその情報に興味があることを保証している。これはメッセージングシステムが情報の種類ごとにMessage Channelsを持っているからだ。アプリケーションが情報を送る時、利用可能なチャネル全てに情報をランダムに付与するわけではない。

チャネルはメッセージングシステム上の論理アドレスであり、実装はプロダクトに依存する。おそらく全てのMessage Endpointは他の全てのエンドポイントへの直接的な接続を持っているか、中央ハブを介して接続されている。おそらくいくつかの別々の論理チャネルは1つの物理チャネルとして設定されているものの、どのメッセージがどの宛先を対象としているかがはっきりしている。定義された論理チャネル群がこれらの詳細設定はアプリケーション側からは隠れている。

メッセージングシステムはメッセージチャネルに対して自動的に事前設定するわけではなく、むしろ開発者が通信に必要なチャネルが何かを決めなければならない。そしてシステム管理者はアプリケーションが期待するチャネルを調整するよう設定しなければならない。いくつかのメッセージングシステム実装はアプリケーションが稼働中に新規チャネルを作成するのをサポートしているが、他のアプリケーションがチャネルを作成するのを知っていなければならないのであまり有用ではない。よって、利用可能なチャネル数と目的はデプロイ時に決定される傾向がある、(このルールには例外があり、詳細は第4章「Messaging Channels」で)

Messagingに関するちょっとしたボキャブラリー

Message Channel経由で通信するアプリケーションを何と呼べばいいのか?似たような用語は沢山ある。最も一般的な用語はおそらくsenderreceiver。他にもproducerconsumerpublishersubscriberなど。また他のアプリケーションが話すチャネル上でlistenすると言う。Webサービスの世界ではrequesterproviderという。古い言い方だとclientserverと言う(ダサい)。

混乱してきた。Webサービスでは、サービスプロバイダにメッセージを送るアプリケーションは、リクエストメッセージを送る場合でもサービスのconsumerと呼ばれる。consumerがproviderにメッセージを送りレスポンスを消費(consume)する、と考えられる。幸いなことに、これはRmote Procedure Invocationでの世界に限られる。メッセージを送ったり受け取ったりするアプリケーションはメッセージングシステムのclientと呼ばれる。もっと特定した言い方だとendpointまたはmessage endpointという。


メッセージングシステムを使い始める際、開発者はチャネルを作成するために本当にすべきことが何かについて気をつけなければならない。開発者はcreateQueueメソッド(Java)やnew MessageQueue(.NET)などのコードで、実際にメッセージングシステム上の新しいキューリソースを割り当てる。単に管理ツールを使ってメッセージングシステムにてすでに作られたリソースへのアクセスを提供するランタイムオブジェクトをインスタンス化しているだけの場合もある。

メッセージングシステムのチャネルを設計する際に気をつける別の問題がある。チャネルはチープだがタダではない。アプリケーションは異なる種類の情報を転送したり同じ情報を沢山の別のアプリケーションに転送したりするために複数のチャネルを必要とする。各チャネルはメッセージを表すためにメモリやディスクスペースを必要とし、たとえ企業システムが無制限のメモリとディスクを持っていたとしても、多くのチャネルを一貫性をもってさばくには何らかの厳しい制限を課すことになる。よってアプリケーションが必要になった際に応じて新しくチャネルを作成する計画において、もし数千のチャネルまたは数千のチャネルが必要なくらいのスケールが求められる場合、高スケーラブルなメッセージングシステム実装を選択し、ニーズを満たすかスケーラビリティをテストする必要がある。

チャンネル名

チャネルが論理アドレスであるなら、これらのアドレスは何に見えるか?多くのケースがあるが詳細はメッセージングシステム実装依存である。にもかかわらず、ほとんどの場合チャネルはMyChannel?のように英数字の名前で参照される。多くのメッセージングシステムは階層構造のチャネル名スキームをサポートしており、ファイルシステムのような方法でチャネルを整理できる。例えばMyCorp?/Prod/OrderProcessing?/NewOrders?MyCorp?の本番アプリケーションで使われているチャネルを示しており、新しい注文情報が含まれている。


メッセージチャネルにはPoint-to-Point ChannelsPublish-Subscribe Channelsの2種類がある。同じチャネル上に異なる種類のデータを混在させると多くの混乱を引き起こす。これを避けるには、別々のDatatype Channelsを使う。Selective Consumerは1つの物理チャネルを論理的に複数のチャネルのようにふるまうことができる。メッセージングを使うアプリケーションは無効なメッセージ用の特別なチャネル(Invalid Message Channel)から恩恵を受けることがしばしばある。Messagingを使いたいがメッセージクライアントへのアクセスを持っていないアプリケーションはChannel Adaptersを使ってメッセージングシステムに接続できる。よくデザインされたチャネル群はアプリケーショングループ全体のメッセージングAPIのようにふるまうMessage Busを形作る。

例:株式取引

株式取引アプリケーションが取引を行う時、取引リクエストのMessage Channel上にリクエストを置く。取引リクエストを処理する別アプリケーションは同じメッセージチャネル上で処理可能なものを探す。もしリクエストしているアプリケーションが株価をリクエストする必要があるなら、株価用に設計された異なるMessage Channelを使うだろう。よって株価リクエストは取引リクエストとは独立している。

例:J2EE JMSリファレンス実装

JMS上でMessage Channelを作成する方法を見てみよう。J2EE SDKにはJMSを含むJ2EEサービスのリファレンス実装が付属している。リファレンスサーバはj2eeコマンドで起動できる。Message Channelsはj2eeadminツールを使って設定する必要がある。このツールでキューとトピックの両方が設定できる。

j2eeadmin -addJmsDestination jms/mytopic topic
j2eeadmin -addJmsDestination jms/myqueue queue

チャネルが作成されるとJMSクライアントコードにてアクセスできる。

Context jndiContext = new InitialContext();
Queue myQueue = (Queue) jndiContext.lookup("jms/myqueue");
Topic myTopic = (Topic) jndiContext.lookup("jms/mytopic");

JNDIルックアップはキュー(トピック)を作成するわけではなく、すでにj2eeadminコマンドにて作成されている。JNDIルックアップは単にJavaでQueueインスタンスを作成しメッセージングシステム上のキュー構造へのアクセスをモデル化し提供している。

例:IBM WebSphere? MQ

もしメッセージングシステム実装がJMSを実装しているIBMのWebSphere? MQ for Javaであれば、WebSphere? MQ JMS管理ツールを使って宛先を作成できる。myQueueという名前のキューを作ってみる。

DEFINE Q(myQueue)

WebSphere? MQ上にキューが存在すると、アプリケーションはキューにアクセスできる。

WebSphere? Application ServerのフルバージョンでないWebSphere? MQはJNDI実装を含んでいないので、J2EE実装で示したようなJNDIルックアップはできない。以下のようにJMSセッションを介してキューにアクセスしなければならない。

Session session = // create the session
Queue queue = session.createQueue("myQueue");

例:Microsoft MSMQ

MSMQはメッセージチャネルを作成したりキューを呼んだりするにあたって様々な方法がある。Microsoft Message Queue ExplorerやComputer Managementコンソール(画像参照)を使ってキューを作成できる。ここからキューを設定したり削除したりできる。

また、コードでキューを作成できる。

using System.Messaging;
...
MessageQueue.Create("MyQueue");

キューが作成されると、MessageQueueインスタンスが生成されキュー名が渡されることで、アプリケーションはアクセスできるようになる。

MessageQueue mq = new MessageQueue("MyQueue");

担当者のつぶやき

みんなの突っ込み