メッセージキュー(MSMQ)

System.Messaging名前空間に含まれるクラスは、Windowsオペレーティングシステムのメッセージキュー機能を使用して、情報の読み取りと書き込みを行うことができます。メッセージング機能は、切断された環境で機能します。

 

同期プログラミングでは、メソッドを呼び出すときに、呼び出し元はメソッドの実行が完了するのを待つ必要があります。非同期プログラミングでは、呼び出しスレッドは並列で実行されるメソッドを開始できます。非同期プログラミングは、委任またはクラスライブラリによって実装できます。非同期メソッドまたはスレッドをサポートします。同期および非同期プログラミングでは、クライアントとサーバーを同時に実行する必要があります。

 

MSMQは非同期で実行されますが、クライアント(送信者)はサーバー(受信者)が送信されたデータを読み取るのを待たないため、MSMQは切断された環境で実行できます。データを送信するとき、受信者はオフラインになることがあります。将来的には、受信者がオンラインになると、送信側アプリケーションの介入なしにデータが受信されます。

 

MSMQは、接続が切断されているときに使用できます。eコマースサイトでは、サーバーが特定の瞬間に注文とトランザクションでいっぱいになると仮定しますが、夜間は負荷が非常に低くなります。1つの解決策は、より高速なサーバーを購入することです。ピーク注文を処理するためにサーバーをシステムに追加するか、サーバーを追加します。低コストのソリューションもあります。トランザクションを高負荷の期間から低負荷の期間に移動します。つまり、ピークとフラット化です。このスキームでは、注文はメッセージキューに送信され、受信側はデータベースシステムにとって有益な速度で注文を読み取ります。これで、システムの負荷が軽減され、サーバー処理トランザクションはデータベースシステムをアップグレードするよりも安価になります。



1つは、MSMQの機能です
MSMQはWindowsオペレーティングシステムの一部です。このサービスの主な機能は次のとおりです。
1.メッセージは切断された環境で送信でき、送信アプリケーションと受信アプリケーションを同時に実行する必要はありません。
2.高速モードを使用すると、メッセージを非常にすばやく送信できます。高速モードでは、メッセージはメモリに保存されます。
3.回復メカニズムの場合、メッセージは保証された配信方法を使用して送信でき、回復可能なメッセージはファイルに保存され、サーバーの再起動時に送信されます。
4.メッセージキューは、送信できるユーザーまたはキュー内のいくつかのメッセージを決定するアクセス制御リストによって保護されています。メッセージを暗号化して、ネットワークスニファがデータを読み取らないようにすることもできます。
5.メッセージ送信時に優先度を指定できるため、高品質なアイテムをより高速に処理できます。
6. MSMQは、マルチキャストメッセージの送信をサポートします
7.トランザクションメッセージキューでは、メッセージはDTCトランザクションに参加できます。

次に、MSMQをインストールします
Windows XPでは、「プログラムの追加と削除」を使用すると、Windowsコンポーネントに別のセクションが表示され、MSMQオプションを選択できます。また、MSMQオプションでは、次のコンポーネントを選択できます。
共通:MSMQの基本機能には共通サブコンポーネントが必要です
Active Directory統合:これを使用すると、メッセージキュー名カクテルがActive Directoryに書き込まれます。このオプションを使用すると、Active Directory統合を使用してキューを検索し、Windowsユーザーおよびグループでキューを保護できます。
MSMQ Httpサポート:HTTPプロトコルを使用してメッセージを送受信できます。
トリガー:トリガーを使用して、新しいメッセージを受信したときにアプリケーションをインスタンス化できます。

メッセージキューをインストールする場合は、メッセージキューサービスを開始する必要があります。このサービスは、メッセージを読み取り、他のメッセージキューサーバーと通信し、メッセージをネットワークにルーティングします。

3、MSMQ構造
メッセージキューを使用すると、メッセージキューからメッセージを読み書きできます。
(1)ニュース
メッセージはメッセージキューに送信されます。メッセージにはメッセージ本文とメッセージタイトルが含まれます。任意のメッセージをメッセージウェイトに配置できます。メッセージはメッセージ本文に配置できます。
メッセージのタイトルと本文に加えて、メッセージには送信者、タイムアウト構成、トランザクションID、または優先度も含まれます
メッセージキューには、いくつかの種類のメッセージがあります。
一般的なメッセージ:アプリから送信
確認メッセージ:一般メッセージの状況を報告し、メッセージが管理キューに送信されたことを確認し、一般メッセージの送信が成功したかどうかを報告します。
応答メッセージ:元の送信者が何らかの応答を必要とする場合、それは受信アプリケーションによって送信されます。
レポートメッセージ:MSMQシステムによって生成され、テストメッセージとトレースルートメッセージはこのカテゴリに属します。

メッセージには、メッセージがキューから読み取られる順序を定義する優先度を設定できます。キューから読み取られたメッセージは、優先度が最も高いメッセージです。

メッセージの配信モードには、エクスプレスモードとリカバリ可能モードの2つがあります。
エクスプレスメッセージの配信速度は非常に高速です。これは、メッセージの保存にメモリのみが使用され、メッセージが宛先に配信されるまで、ルーティングのすべての段階で回復可能なメッセージがファイルに保存されるためです。このようにして、コンピュータが再起動したり、ネットワークに障害が発生した場合でも、メッセージの送信を保証できます。
トランザクションメッセージは、回復可能なメッセージの特別なバージョンです。トランザクションメッセージの送信中に、メッセージが宛先に1回だけ到着し、送信された順序で宛先に到着することを保証できます。優先順位を設定することはできません。トランザクションメッセージで使用されます。

(2)メッセージキュー
メッセージキューはメッセージライブラリであり、ディスクに保存されているメッセージは/ system32 / msmq / storageディレクトリにあります。

4、MSMQプログラミングの実現
(1)メッセージキューを作成する
メッセージキューは、MessageQueueクラスのCreate()メソッドを使用してプログラムで作成することもできます。Create()メソッドでは、新しいキューのパスを送信する必要があります。パスには、キューが配置されているホストの名前と、キューの名前。次に例を示します。ローカルホストにキューMyNewPublicQueueを作成するには、プライベートキューを作成するために、パス名に/ Private $ / MyNewPrivateQueueなどのPrivate $を含める必要があります。
Create()メソッドを呼び出した後、キューのプロパティを変更できます。Labelプロパティを使用して、キューのラベルをDemo Queueに設定します。サンプルプログラムは、キューのパスとフォーマット名をコンソールに書き込みます。フォーマット名前はUUIDで自動的に作成されます。UUIDサーバー名なしでキューにアクセスするために使用できます。
static void Main(string [] args)
{{
 using(MessageQueue queue = MessageQueue.Create(@ "./ MyNewPublicQueue"))
 {{
  queue.Label = "デモキュー";
  Console.WriteLine( "作成されたキュー:");
  Console.WriteLine( "Path:{0}"、quequ.Path);
  console.WriteLine( "FormatName:{0}"、queue.FormatName);
 }
}
注意:
キューを作成するときは、管理権限が必要です。通常、アプリケーションのユーザーに管理権限を持たせることはできません。そのため、通常、キューはインストーラーによって作成されます。MessageQueueInstallerクラスを使用してメッセージキューを作成することもできます。

(2)キューを見つける
パス名とフォーマット名を使用してキューを識別できます。キューを見つけるには、パブリックキューとプライベートキューを区別する必要があります。パブリックキューはActiveDirectoryで公開されます。これらのキューの場合、それらが配置されているシステムを知る必要はありません。プライベートキューは、キューが配置されているシステムの名前がわかっている場合にのみ見つけることができます。
Active Directoryドメインでキューのラベル、カテゴリ、または形式名を検索すると、パブリックキューを見つけて、マシン上のすべてのキューを取得できます。の静的メソッドGetPublicQueuesByLabel()、GetPublicQueuesByCategory()、およびGetPublicQueuesByMachine() MessageQueueクラスを取得できます。Queue、GetPublicQueues()メソッドは、ドメイン内のすべてのパブリックキューを含む配列を返します。
static void Main(string [] args)
{{
 foreach(MessageQueue.GetPublicQueues()のMessageQueueキュー)
 {{
   Console.WriteLine(queue.Path);
 }
}
GetPublicQueues()メソッドはオーバーロードされており、オーバーロードされたバージョンでは、MessageQueueCriteriaクラスのインスタンスを送信できます。このクラスを使用して、特定の時間の前後に作成または変更されたキューを検索します。また、キューのカテゴリ、ラベル、またはマシン名を見つけることもできます。
プライベートキューは、静的メソッドGetPrivateQueuesByMachine()を使用して取得できます。このメソッドは、指定されたシステム内のすべてのプライベートキューを返します。

(3)既知のキューを開きます
キュー名がわかっている場合は、それを取得する必要はありません。キューは、パスまたはフォーマット名を使用して開くことができます。パスまたはフォーマット名は、MessageQueueクラスのコンストラクターで設定されます。
パスは、キューを開くために必要なマシン名とキュー名を指定します。次のコード例は、ローカルホストでキューMyPublicQueueを開きます。キューが存在するかどうかを判断するために、静的メソッドMessageQueue.Exists()が使用されます。
static void Main(string [] args)
{{
  if(MessageQueue.Exists(@ "./ MyPublicQueue"))
  {{
    MessageQueue queue = new MessageQueue(@ "./ MyPublicQueue");
  }
  そうしないと
  {{
   Console.WriteLine( "キュー./MyPublicQueueは存在しません");
  }
}

キューのタイプに応じて、キューを開くときに異なる識別子が必要です。以下は、指定されたタイプのキュー名の構文です。
パブリックキューMachineName / QueueName
プライベートキューMachineName / Private $ / QueueName
ジャーナルキューMachineName / QueueName / Journal $
マシンログキューMachineName / Journal $
Machine Dead Letter Queue MachineName / DeadLetter $
マシントランザクションデッドレターキューMachineName / XactDeadLetter $
パス名を使用してパブリックキューを開く場合は、マシン名を送信する必要があります。マシン名が不明な場合は、代わりにフォーマット名を使用できます。プライベートキューのパス名は、ローカルシステムでのみ使用できます。プライベートキューにリモートアクセスするには、フォーマット名を使用する必要があります。

パス名に加えて、フォーマット名を使用してキューを開くこともできます。フォーマット名は、Active Directoryでキューを取得し、キューが配置されているホストを取得するために使用されます。切断された環境では、メッセージをキューに送信され、メッセージを送信できません。キューに送信するには、この時点でフォーマット名を使用する必要があります。
MessageQueue queue = new MessageQueue(@ "FormatName:PUBLIC = 09816AFF-3608-4c5d-B892-69754BA151FF");
フォーマット名は、プライベートキューを開いて、使用するプロトコルを指定することもできます
a。プライベートキューにアクセスするには、文字列FormatName:PRIVATE = MachineGUID / QueueNumberをコンストラクターに渡す必要があります。キューを作成すると、プライベートキューのキュー番号が生成されます。キュー番号は<windows> /にあります。下のSystem32 / msmq / storage / lqsディレクトリ。
b。FormatName:DIRECT = Protocol:MachineAddress / QueueNameを使用して、メッセージの送信に使用されるプロトコルを指定します。
c、FormatName:DIRect = OS:MachineName / QueueNameは、フォーマット名を使用してキューを指定するもう1つの方法です。現時点ではプロトコルを指定する必要はありませんが、マシン名とフォーマット名は引き続き使用できます。

(4)メッセージを送信する
MessageQueueクラスのSendメソッドを使用して、メッセージをキューに送信します。Send()メソッドにパラメーターとして渡されたオブジェクトは、関連するキューにシリアル化されます。Send()メソッドがオーバーロードされるため、ラベルとMessageQueueTransactionがオーバーロードされます。オブジェクトを送信でき、パス名は次のとおりです。サーバー名はローカルシステムを示すために「。」を指定し、プライベートキューのパス名はローカルでのみ使用できます。
static void Main(string [] args)
{{
 試してみてください
  {{
    if(!MessageQueue.Exists(@ "./ Private $ / MyPrivateQueue"))
    {{
         MessageQueue.Create(@ "./ Private $ / MyPrivateQueue");
    }
    MessageQueue queue = new MessageQueue(@ "./ Private $ / MyPrivateQueue");
    queue.Send( "サンプルメッセージ"、 "ラベル");
  }
  catch(MessageQueueException ex)
  {{
      Console.WriteLine(ex.Message);
  }
}
メッセージはxmlでフォーマットされ、メッセージのフォーマットはメッセージキューに接続されたフォーマッターの機能です。

複雑なメッセージを送信するには、文字列の送信に加えて、MessageQueueクラスのSend()メソッドにオブジェクトを送信することもできます。このクラスのタイプはいくつかの特別な要件を満たす必要がありますが、フォーマッターによって異なります。バイナリフォーマッターの場合、このクラスは、[Serializable]属性を使用してシリアル化する必要があります。.netランタイムライブラリのシリアル化関数を使用してすべてのフィールド(プライベートフィールドを含む)をシリアル化し、ISerializableインターフェイスを実装してカスタムシリアル化を定義します。XMLシリアル化XMLフォーマッタが使用されます。 XMLシリアル化プロセスでは、すべてのパブリックフィールドと属性がシリアル化されます。System.Xml.Serializationネームスペースで属性を使用すると、xmlシリアル化に影響を与える可能性があります。

(5)メッセージフォーマッタ
キューに送信されるメッセージの形式は、フォーマッターによって異なります。MessageQueueクラスには、フォーマッターを指定できるFormatterプロパティがあります。デフォルトのフォーマッターXmlMessageFormatterは、メッセージをXML構文でフォーマットします。
メッセージフォーマッタはIMessageFormatterインターフェイスを実装します。System.Messaging名前空間には3つのメッセージフォーマッタがあります。
XmlMessageFormatterは、XMLシリアル化オブジェクトを使用するデフォルトのフォーマッターです。BinaryMessageFormatterを使用すると、メッセージをバイナリ形式でシリアル化できます。これらのメッセージは、XMLを使用してフォーマットされたメッセージよりも短くなります。ActiveXMessageFormatterはバイナリフォーマッターであるため、COMオブジェクトを使用して読み取りと書き込みを行うことができます。このフォーマッタを使用すると、.netクラスを使用してメッセージをキューに書き込み、COMオブジェクトを使用してキューからメッセージを読み取ることができます。その逆も可能です。

(6)メッセージを受信する
メッセージを読み取るには、MessageQueueクラスを使用することもできます。Receive()メソッドを使用してメッセージを読み取り、キューからメッセージを削除できます。メッセージが異なる優先度を使用して送信される場合は、最も高いメッセージを読み取ります。優先度、同じ優先度のメッセージを読み取る場合、ネットワーク内のメッセージ送信順序が保証されないため、最初に送信されたメッセージが最初に読み取られない場合があります。送信順序と読み取り順序が同じであることを確認するには、次のことができます。トランザクションメッセージキューを使用します。
static void Main(stirng [] args)
{{
 MessageQueue queue = new MessageQueue(@ "、/ Private $ / MyPrivateQueue");
 queue.Formatter = new XmlMessageFormatter(new string [] {"System.String"});
 メッセージmessage = queue.Receive();
 Console.WriteLine(message.Body);
}
Receive()メソッドは同期的に実行されます。キューにメッセージがない場合は、キューにメッセージがあるときに実行されます。

1.メッセージを列挙する
Receive()メソッドを使用してメッセージを1つずつ読み取るだけでなく、列挙子を使用してIEnumerableインターフェイスを実装するすべてのMessageQueueクラスを反復処理できるため、foreachステートメントで使用できます。反復子メッセージの使用は行われません。キューから削除されましたが、コンテンツを表示できます。
MessageQueue queue = new MessageQueue(@“ ./ Private $ / MyPrivateQueue”);
queue.Formatter = new XmlMessageFormatter(new string [] {"System.String"});
foreach(キュー内のメッセージメッセージ)
{{
 Console.WriteLine(message.Body);
}
IEnumerableインターフェイスを使用しない場合は、MessageEnumeratorクラスを使用することもできます。MessageEnumeratorはIEnumeratorインターフェイスを実装します。その他の機能があります。IEnumerableインターフェイスを実装すると、メッセージがキューから削除されなくなります。 MessageEnumeratorクラスは、列挙子から取得できます。現在のカーソル位置にあるメッセージを削除します。

MessageQueueクラスのGetMessageEnumerator()メソッドを使用してMessageEnumeratorにアクセスします。MessageEnumeratorのMoveNext()メソッドを使用して、メッセージに1つずつアクセスできます。MoveNext()メソッドは、パラメーターとして期間を取るためにオーバーロードされます。これは、この列挙子を使用する主な利点です。スレッドは、指定された期間内にメッセージがキューに入るのを待ってから待機しません。IEnumeratorインターフェイスによって定義されたCurrentプロパティは、メッセージへの参照を返します。
MessageQueue queue = new MessageQueue(@“ ./ Private $ / MyPrivateQueue”);
queue.Formatter = new XmlMessageFormatter(new string [] {"System.String"});
using(MessageEnumerator messages = queue.GetMessageEnumerator())
{{
  while(messages.MoveNext(TimeSpan.FormMinutes(30)))
   {{
     メッセージmessage = message.Current;
    Cosole.WriteLine(message.Body);
   }
}

2、非同期読み取り
MessageQueueクラスのReceiveメソッドは、キュー内のメッセージを読み取ることができるまで待機します。スレッドの実行を妨げることを避けるために、Receiveメソッドのオーバーロードバージョンでタイムアウト設定を指定できます。タイムアウトからのキューでは、Receive()メソッドを再度呼び出す必要があります。ここではメッセージをクエリしませんが、BeginReceive()非同期メソッドを呼び出すことができます。BeginReceive()を使用して非同期読み取りを開始する前に、ReceiveCompletedを設定する必要がありますイベント。ReceiveCompletedイベントは、ReceiveCompletedEventHandlerに委任する必要があります。これは、キューに到着するメッセージと、メッセージを読み取ることができるときに呼び出されるメソッドを参照します。
MessageQueue queue = new MessageQueue(@“ ./ Private $ / MyPrivateQueue”);
queue.Formatter = new XmlMessageFormatter(new string [] {"System.String"});
queue.ReceiveCompleted + = new ReceiveComletedEventHandler(MessageArrived);
queue.BeginReceive();

MessageArrivedハンドラーには2つのパラメーターが必要です。最初のパラメーターはイベントソースMessageQueueで、2番目のパラメーターはメッセージと非同期結果を含むReceiveCompletedEventArgsタイプです。EndReceive()メソッドは、非同期メソッドの結果を取得するために呼び出されます。つまり、メッセージ:
public static void MessageArrived(object source、ReceiveCompletedEventArgs e)
{{
  MessageQueue queue =(MessageQueue)source;
  メッセージmessage = queue.EndReceive(e.AsyncResult);
  Console.WriteLine(message.Body);
}
メッセージをキューから削除しない場合は、BeginPeek()メソッドとEndPeek()メソッドを非同期I / Oで使用できます。

5、トランザクションキュー
リカバリ可能なメッセージの場合、メッセージの受信順序は保証できません。また、メッセージが1回だけ受信されることも保証できません。ネットワーク障害により、メッセージが複数回受信される可能性があります。送信者と受信者に複数のネットワークがインストールされている場合メッセージキュー契約の場合、これも発生します。
メッセージを受信する順序を確認し、メッセージを1回だけ受信する必要がある場合は、トランザクションキューを使用できます。
メッセージが受信される順序は、メッセージが送信された順序と同じであり、メッセージは1回だけ受信されます。

トランザクションキューの場合、トランザクションはメッセージと送受信プロセスにまたがることはできません。メッセージキューの本質は、送信と受信の時間が非常に長く、トランザクション処理が非常に短いことです。メッセージキューでは、最初のトランザクションがmessageキューでは、2番目のトランザクションがメッセージをネットワークに書き込み、3番目のトランザクションがメッセージの受信に使用されます。
MessageQueue.Create()メソッドの2番目のパラメーターにtrueを渡すと、トランザクションメッセージキューが作成されます。
トランザクションのキューに複数のメッセージを書き込む場合は、MessageQueueTransactionオブジェクトをインスタンス化し、Begin()メソッドを呼び出す必要があります。トランザクションに属するすべてのメッセージを送信した後、MessageQueueTranscactionオブジェクトのCommit()メソッドを呼び出す必要があります。キャンセルするにはトランザクションの場合、catchブロックでAbort()メソッドを呼び出す必要があります。
static void Main(string [] args)
{{
  if(!MessageQueue.Exists(@ "./ MyTransactionalQueue"))
   {{
        MessageQueue.Create(@ "./ MyTransactionalQueue"、true);
   }
   MessageQueue queue = new MessageQueue(@ "./ MyTransactionalQueue");
   MessageQueueTransaction transaction = new MessageQueueTransaction();
  
   試してみてください
   {{
      transaction.Begin();
      queue.Send( "a"、transaction);
      queue.Send( "b"、transaction);
      queue.Send( "c"、transaction);
       transaction.Commit();
   }
   キャッチ
   {{
       transaction.Abort();
   }

}

おすすめ

転載: blog.csdn.net/jinzhengquanqq/article/details/5872208