この記事は機械翻訳されたものです。
天気予報: 曇り
AppFabric の Queues によってシリーズを終える (機械翻訳)
10 月号では、私はいくつかの新機能 Windows Azure AppFabric サービス バスで触れた (msdn.microsoft.com/magazine/hh456395)。 今月は、次の往復を開始したシナリオを続けます。 これまでのところ、シナリオでは、ストア、インベントリのチェック近くの店から在庫チェック要求を発行すると、トピックに要求しています。 トピックを購読して、ストア彼らが自分の地域内にメッセージの制限し、送信されないサブスクリプションのフィルターに基づいて、要求を受け取った。
戻りの旅行のために、私は Windows Azure AppFabric サービス バス キューの機能のいくつかに依存します。 まず、ある 2 つの重要なプロパティには、トピックに送信される、BrokeredMessage の値を割り当てます。 最初のプロパティには値を割り当てます、受信者にメッセージを送信するには、ここで教えて ReplyTo プロパティ、です。 これは、特定のキューの送信者が、メッセージを送信時に作成されます。 応答は、放送には誰も聞いて助けを同一視要求パターンとは異なり、1 人の受信者であるため、トピックの代わりにこのケースでは、キューを使用したいと思います。
メッセージの流れの新しい部分に表示されます図 1と店の行の右側に流れる。
図 1 お問い合わせと応答のラウンドト リップ
送信要求コードを更新
最初のパスでは、メッセージをトピックに出たし、適切なサブスクリプションでは、それを拾うことを示したが、2 つの重要な項目は、ニース、簡単な応答をサポートするために元に戻すに残っていた。 最初の項目は、CorrelationId プロパティは、BrokeredMessage の設定です。 私は私のデータ クラスまたはスキーマの一部として含めることはありませんので、プロパティ、API の一部です。 文字列であるため、それ何か意味のあることができるが何か一致する CorrelationId を持つ任意の応答システムにいくつかの他の要求と一致すると混同することはできませんが、メッセージを一意に識別する必要があります。 私のサンプルのため、GUID を使用するが、実際はかなり安全な賭けも。 コードは次のとおりです。
BrokeredMessage msg = BrokeredMessage.CreateMessage(data);
// Add props to message for filtering
msg.Properties["Region"] = data.Region;
msg.Properties["RequesterID"] = data.RequesterID;
// Set properties for message
msg.TimeToLive = TimeSpan.FromSeconds(30);
msg.ReplyTo = returnQueueName;
msg.CorrelationId = Guid.NewGuid().ToString();
BrokeredMessage は、セッション Id は、私はここで使用していないという名前のプロパティもあります。 セッション Id は、すべて関連メッセージのグループ化を容易にするためは、メッセージ エンベロープ レベルがいい論理グループ化を別のプロパティです。 質問は、どのように CorrelationId 意図でちがうが発生します。 これには、SessionId を特に役に立つかもしれない 2 つのシナリオがあります。 最初は複数のデーモンさまざまな要求をすべてして、システムに関連しています。 CorrelationId 要求のプロセッサへの応答をルーティングに使用されます。 SessionId すべて送受信処理ノード間でのメッセージのグループ化に使用されます。 このようなグループは、解析システムにおける処理とデバッグの状態を決定する際に便利です。 同じ理由から、この便利なコンストラクトは多く、全体のプロセスの一部として要求するシステムで (例については、購入プロセスを支払い方法の検証、インベントリのチェック送信履行するように)、しかしではない正確な流れとタイミングを保証します。
CorrelationId を送信メッセージに設定し、私はする必要があります、次の変更 ReplyTo プロパティを設定することです。 私は可能性がある別の話題を作成して応答を監視または、1 つのキューを使用するすべてのストアは、不要なトラフィックを作成して回負荷の下では、ボトルネックが発生する可能性が高いことが したがって、それ単に要求時の応答キューを作成し、受信者は、知っている意味します。 これは文字列であるため、任意の混乱や、ソフトウェアの将来の進化の衝突を防ぐために、完全修飾名をお勧めしますが、何かをことができます。 キュー名にのみを開始できませんでしたが、複数のサービス バスの名前空間とサブキューをサポートするために、システムを起動するとメンテナンスの下での拡張、この混乱を可能性があります。 さらに、完全修飾アドレスは、Microsoft を使用していない受信者に良くなります。ネット フレームワーク。
私は、メッセージを送信する前に行う最後の 2 つのことです応答キューを作成し、応答を確認するには、タイマーを開始します。 私は、GetQueue メソッドを開始しました。 この書き込みは、ドキュメントの (bit.ly/pnByFw) Microsoft.ServiceBus.Messaging.Queue;「返すは「型」「価値を相当 GetQueue 状態の キュー ハンドルをキュー; または、キュー、サービスの名前空間に存在しない場合は null です。 ただし、この場合ではないです。 実際には、例外がスローされます。
// Check if-exists and create response queue
try
{
returnQ = this.ServiceBusNSClient.GetQueue(returnQueueName);
}
catch (System.Exception ex)
{
Debug.WriteLine(ex.Message);
}
if (returnQ == null)
{
returnQ = this.ServiceBusNSClient.CreateQueue(returnQueueName);
}
checkQTimer.Enabled = true;
したがって、私は、GetQueue メソッドを try catch ブロックでラップし、移動しました。 典型的な私のサンプル コード、何も以上のつ書き込みエラーは。 キューが作成されると、キューのチェックを参照にし、[アプリケーションの開始時に設定、タイマーを有効にすることができますので私はそれを変数に割り当てます。
受信者の更新と応答
適切な変更を側に、私は、要求に対応することができますのでいくつかの追加しなければ。 私は使用するつもりはほとんどハードコードされた応答が、私は、1 つを私は返事をしますを選択する、グリッド内のメッセージを一覧表示するつもり。 私は、UI の新しいメッセージを通知は、イベント メカニズムを設定しています。 メッセージを受け取ったら、レスポンダーとして、現在の受信者のストア ID を設定し、[メッセージ表示用の UI を通知します。
recvSuccess = msgReceiver.TryReceive(TimeSpan.FromSeconds(3), out NewMsg);
if (recvSuccess)
{
CreateInquiry.InventoryQueryData qryData =
NewMsg.GetBody<CreateInquiry.InventoryQueryData>();
NewMsg.Properties.Add("ResponderId", this.StoreID);
EventContainer.RaiseMessageReceived(NewMsg);
}
UI には、受信メッセージは [必要 InvokeRequired メソッド チェックを行います、UI 要素を更新するには、メソッドに渡すイベントに加入します。
void EventContainer_MessageReceivedEvent(object sender, MessagingEventArgs e)
{
BrokeredMessage msg = (BrokeredMessage)e.MessageData;
var RequestObject =
msg.GetBody<CreateInquiry.InventoryQueryData>();
RequestObject.ResponderID = msg.Properties["ResponderId"].ToString();
this.ReceivedMessages.Add(RequestObject);
UpdateUIElements(msg.MessageId, RequestObject);
}
完全なコードをについては、メッセージを取得し、UI を更新する私今来るメッセージを視覚化できます (を参照してください図 2)。
図 2 在庫トピック モニター
(私ではなかった雇用私ユーザーの経験デザインのスキルを明らかに) この UI は、メッセージのいずれかを選択し、それに数量が、下のテキスト ボックスでの設定に対応できるようになります。 私はのみ数量メッセージ オブジェクトを設定し、メッセージの ReplyTo プロパティで指定したキューに送信するコードの小さなビットを追加する必要がある応答コードは非常にシンプルで短い作業になります。
このサンプルでは、私単に受信したメッセージからトピック文字列 < BrokeredMessage > 辞書を追加しています。 私は、BrokeredMessage.MessageId を使っています、ディクショナリのキーとしてはオブジェクト。 私は単にディクショナリから取得し、同じ CorrelationId を割り当てると、ResponderId および量のプロパティに値を割り当て、新しい BrokeredMessage を作成するメッセージ Id、グリッドからを使用します。 だけからトピックを受信するとき、私は、MessagingFactory、QueueClient を作成してから、MessageSender オブジェクトを使用しますので。
// Send message
SharedSecretCredential credential =
TransportClientCredentialBase.CreateSharedSecretCredential(
Constants.issuerName, Constants.issuerKey);
Uri sbUri = ServiceBusEnvironment.CreateServiceUri(
"sb", Constants.sbNamespace, String.Empty);
MessagingFactory Factory = MessagingFactory.Create(sbUri, credential);
QueueClient QClient = Factory.CreateQueueClient(msg.ReplyTo);
MessageSender Sender = QClient.CreateSender();
Sender.Send(ResponseMsg);
私たちは、私たちの焦点は応答を処理する、元のアプリケーションに戻る必要があるので、戻るの応答を送信します。
応答の受信
このサンプルでは、私は、応答キューのオフをプルするします。 ReplyTo キューの監視を開始する要求を送信するには、コードが修正されたため、私は本当に、実際のコードでキューをチェックを追加します。 MessageReceiver の作成を開始し、単純な設定すべての利用可能なメッセージをキューにこの時期をループ中。
void checkQTimer_Tick(object sender, EventArgs e)
{
MessageReceiver receiver =
QClient.CreateReceiver(ReceiveMode.ReceiveAndDelete);
BrokeredMessage NewMessage = null;
while (receiver.TryReceive(TimeSpan.FromSeconds(1), out NewMessage))
{
InquiryResponse resp = new InquiryResponse();
resp.CorrelationID = NewMessage.CorrelationId;
resp.Message = NewMessage;
InquiryResponses.Add(resp);
}
}
前で、TryReceive メソッドを使用するように。 このサンプルの動作中に、メソッドは、スレッドをブロックするため私は少し異なる実際の UI には、やってしたがって自体より、別のスレッドで実行する貸出考えます。 オブジェクトを作成し、CorrelationId を使用して、オブジェクトを後でフィルターするので全体の BrokeredMessage リストから CorrelationId を取得したいと思います。 私は今私の InquiryData のオブジェクトをカプセル化する BrokeredMessage の封筒の一部であるデータをするので、メッセージは BrokeredMessage としては、欲しい (を参照してください図 3)。
図 3 お問い合わせ要求と応答
リスト ボックスの SelectedIndexChanged コードを変更、私は単に、アイテムとして使用、CorrelationId つかみそれを使用して関心の間の応答表示としては、キューに造ってリストの応答を取得します。
string correlationId =
lbRequests.SelectedItem.ToString();
List<InquiryResponse> CorrelatedList =
InquiryResponses.FindAll(
delegate(InquiryResponse resp)
{
return resp.CorrelationID == correlationId;
});
仕事の最後のビット私の在庫の問い合わせへの回答、店を見るに、DataGrid のレスポンスを追加することです。 私の不毛の UI の美に追加は Guid を使用しているが、私は厄介な Guid と Id の拡張の詳細ページを残してこのわかりやすい説明で、置き換えられるだろう、読者になることを期待するかがわかります。
Review
陸軍っ子としての成長をした後、私は言葉と私の頭の中にやけどを負ったなどの他のものの多くがあります。 1 つの例、「軍事法」は私たちが何をしようとしているよ、私たちやるし、、私たちがやったよ教育のです。 まあ、」は何で「私の部分。 私は 1 つのエントリとしては、この記事の執筆を開始が、あまりにも多くの 1 つの列に、完全なラウンド トリップをアドレスします。 私は、2 つのエントリに分割するように: を要求と、2 番目戻る応答を取得するを取得します。 私の目標は、Windows Azure の AppFabric ServiceBus の基本的な機能が存在し、それを使用して、一般的な感じを与えることでした。 技術について考えるとき、私は常に、コンテキストのいくつかのタイプのラップするように、ここで私は、inter-store 製品のクエリは、それは実現可能なシナリオであり、トピックとキューの両方の組み合わせを使用する意味があるために、コンテキスト。
この記述は、Windows Azure アプリケーションの可能性があります CTP の布 ServiceBus がリリースされているし、いくつかの情報をで見つけることができます bit.ly/it5Wo2。 また、フォーラムに参加できます bit.ly/oJyCYx。
Joseph Fultz ヒューレット ・ パッカード株式会社作業グッドエイチピードットコム グローバル宣言の一部として、ソフトウェア アーキテクトであります。以前、彼は、ソフトウェア アーキテクト、一流企業と ISV の顧客のアーキテクチャと設計ソリューションを定義する Microsoft のだった。
この記事のレビュー、技術スタッフのおかげでに: Jim Keane