動的にルーティングの設定を変えられるルーター
複数の送信先間のメッセージを振り分けるのに、Message Routerを使える。
どのように効率よく管理しながらすべての送信先に対するルータの依存性を排除できる?
適切な送信先に直接メッセージをルーティングできるので、Message Routerは非常に効率的
分散ルーティングは複数のメッセージ受信者がいるのかあるいは全くいないのか、というリスクにさらされる(意味不明)
これを正確に執り行うのに、Message Routerを使う必要がある
送信先を共有する特別な設定用メッセージに基づいて自己設定できるようなDynamic Routerを使う
通常使われる入力と出力のチャネルに加え、Dynamic Routerには制御チャネルがある
最も基本的なシナリオとしては、それぞれの関係者がその存在とルーティングの設定をDynamic Routerの起動時に通知するもの
制御チャネルを拡張して、関係者が購読と解除のメッセージをDynamic Routerに送れるようにするのは道理にかなう
受信者はお互いに独立している
Dynamic Routerの主な欠点
Dynamic RouterはローレベルのIPネットワーク機器のようにメッセージベースのミドルウェアが動いている、もう一つの例である
Dynamic Routerの一般的な利用例はSOAの動的サービスディスカバリー
関連パターン
Content-Based Routerの例を拡張
class DynamicRouter { protected MessageQueue inQueue; protected MessageQueue controlQueue; protected MessageQueue dunnoQueue; protected IDictionary routingTable = (IDictionary)(new Hashtable()); public DynamicRouter(MessageQueue inQueue, MessageQueue controlQueue, MessageQueue dunnoQueue) { this.inQueue = inQueue; this.controlQueue = controlQueue; this.dunnoQueue = dunnoQueue; inQueue.ReceiveCompleted += new ReceiveCompletedEventHandler(OnMessage); inQueue.BeginReceive(); controlQueue.ReceiveCompleted += new ReceiveCompletedEventHandler(OnControlMessage) controlQueue.BeginReceive(); } protected void OnMessage(Object source, ReceiveCompletedEventArgs asyncResult) { MessageQueue mq = (MessageQueue)source; mq.Formatter = new System.Messaging.XmlMessageFormatter(new String[] {"System.String,mscorlib"}); Message message = mq.EndReceive(asyncResult.AsyncResult); String key = ((String)message.Body).Substring(0, 1); if (routingTable.Contains(key)) { MessageQueue destination = (MessageQueue)routingTable[key]; destination.Send(message); } else dunnoQueue.Send(message); mq.BeginReceive(); } // control message format is X:QueueName as a single string protected void OnControlMessage(Object source, ReceiveCompletedEventArgs asyncResult) { MessageQueue mq = (MessageQueue)source; mq.Formatter = new System.Messaging.XmlMessageFormatter(new String[] {"System.String,mscorlib"}); Message message = mq.EndReceive(asyncResult.AsyncResult); String text = ((String)message.Body); String [] split = (text.Split(new char[] {':'}, 2)); if (split.Length == 2) { String key = split[0]; String queueName = split[1]; MessageQueue queue = FindQueue(queueName); routingTable.Add(key, queue); } else { dunnoQueue.Send(message); } mq.BeginReceive(); } protected MessageQueue FindQueue(string queueName) { if (!MessageQueue.Exists(queueName)) { return MessageQueue.Create(queueName); } else return new MessageQueue(queueName); } }
この例ではシンプルなコンフリクト解決メカニズムを使用している