Web/DB プログラミング徹底解説

ホーム > Windows 徹底解説 > マネージド・コードからの COM+ メッセージ・キューの利用 ~ MSMQ 入門

マネージド・コードからの COM+ メッセージ・キューの利用 ~ MSMQ 入門

MQ の概要

メッセージキュー (MQ) は、メッセージの処理を非同期に行います。

MQ は留守番電話に似た仕組みと考えられます。クライアントは、キューに対してメッセージを "録音" します。サーバー側では、キューからメッセージを取り出して "再生" します。 アイデアは新しい物ではありません。

上述の留守番電話の例で言うと、"録音" は Recorder を通して Queue Manager に対して行います。Queue Manager はクライアントとサーバー間の Queue 同士でのメッセージ交換を受け持ちます。サーバー側では、Queue Manager からメッセージを取り出し再生します。キューを監視するコンポーネントは、Listener といい "再生" は Player が行います。

アーキテクチャ

最低でもサーバー上にメッセージを処理するメッセージキューが必要です。 サーバーキューだけではなく、クライアントもキューを持つことができます。 クライアントとサーバー間の接続がある場合は直ちにクライアントのキューは空になり、サーバー上のキューにメッセージが置かれます。

メッセージキューでの登場人物(コンポーネント)は以下の通りです。

  • Recorder
    クライアントからの出力を受け取り、ひとつ以上のメッセージを作成し、ローカルキューまたはプロキシーにそのメッセージを送信する。
  • Listener
    サーバーキューをみて、それをキューから取り出し、Player にメッセージを渡す。
  • Player
    メッセージを受け取る。メッセージの処理などを行うコンポーネントもここに含まれる。


MQ のアーキテクチャ

キューの種類

キューは大きく分けて2種類あります。

  • Application
    プログラムから自動的に、または手動で作成されるキュー。通常アプリケーションが使うキューはこちら。
  • System
    Dead letter queues = 特定の時間内に処理できなかったメッセージが格納される
    Journal queues = アプリケーション、MSMQ またはシステムイベントによって使用される。

使い方シナリオ

  1. すべて手動
    • 手動でキューを作成
    • プログラムから指定したキューにメッセージを置く
    • 明示的にメッセージを取りに行く。
  2. キューを手動で作成。キューに置かれたことだけを自動的に追跡する
    • 手動でキューを作成
    • プログラムで指定したキューにメッセージを配信
    • MSMQのトリガーを使って、条件に応じ、COM+アプリケーションのメソッドを呼び出す
  3. キューの作成も自動化
    • Queued Component を作成する。COM+の属性として Queuing するよう指定するとキューが作成される。
    • 呼び出し側は COM+ コンポーネントのメソッドを呼び出すだけ。

実行例: メッセージキュー作成・メッセージの作成・読み取り、全て手動の場合

MSMQ の有効化

この資料は Windows Vista Ultimate Edition 英語版で動作試験しています。

上の設定で (マイ) コンピュータの [管理] にて Messaging Queuing が表示されることを確認してください。

キューの作成

メッセージ・レコーダの作成

以下の内容を、recorder1.cs として保存します。

using System;
using System.Messaging;

namespace MyTest {

  class Recorder1 {

    public static void Main() {

      //
      // メッセージキューオブジェクトの作成
      //

      MessageQueue TestMQ;

      TestMQ = new System.Messaging.MessageQueue();
      TestMQ.Path = "<コンピュータ名>\\private$\\MyTestQueue1";
      TestMQ.Formatter = new XmlMessageFormatter (new Type[] {typeof(String)});
      TestMQ.MessageReadPropertyFilter.Priority = true;

      //
      // メッセージの作成
      //

      System.Messaging.Message msg;

      msg = new System.Messaging.Message();
      msg.Label = "Hello";
      msg.Body = "This is a sample program.";
      msg.Priority = (MessagePriority) 0;

      //  
      // メッセージキューにメッセージを置く
      //

      TestMQ.Send (msg);

    }

  }
}

以下の内容を makefile として保存します。

CSC = csc.exe

TARGETNAME=recorder1
SOURCE_FILE=recorder1.cs
REF=

OUTDIR=.\chk

all: "$(OUTDIR)\$(TARGETNAME).exe"


"$(OUTDIR)" :
    if not exist "$(OUTDIR)" mkdir "$(OUTDIR)"


CSC_OPT=\
    /nologo\
    /target:exe\
    /out:$(OUTDIR)\$(TARGETNAME).exe\
    /doc:$(OUTDIR)\$(TARGETNAME).xml\
    /debug+\
    /debug:full\
    /optimize-\
    /warn:4


$(OUTDIR)\$(TARGETNAME).exe: "$(OUTDIR)" $(SOURCE_FILE)
    $(CSC) $(CSC_OPT) $(REF) $(SOURCE_FILE)

上記、recorder1.cs と makefile を同じディレクトリに保存してください。 nmake のある、Visual Studio Command Prompt 等から nmake を実行してビルドしてください。


> nmake -a

Microsoft (R) Program Maintenance Utility Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.

  if not exist ".\chk" mkdir ".\chk"
  csc.exe  /nologo /target:exe /out:.\chk\recorder1.exe 
/doc:.\chk\recorder1.xml
  /debug+ /debug:full /optimize- /warn:4  recorder1.cs

> 

メッセージ・プレイヤーの作成

以下の内容を、player1.cs として保存します。

using System;
using System.Messaging;

namespace MyTest {

  class Player1 {

    public static void Main() {

      //
      // メッセージキューオブジェクトの作成 
      //

      MessageQueue TestMQ;

      TestMQ = new System.Messaging.MessageQueue();
      TestMQ.Path = "<コンピュータ名>\\private$\\MyTestQueue1";
      TestMQ.Formatter = new XmlMessageFormatter (new Type[] {typeof(String)});
      TestMQ.MessageReadPropertyFilter.Priority = true;

      //
      // メッセージの取得
      //

      System.Messaging.Message msg;

      try {
        msg = TestMQ.Receive (new TimeSpan(5));
      }
      catch (MessageQueueException e) {
        Console.WriteLine ("No message to retrieve. {0}", e.Message);
        return;
      }

      Console.WriteLine ("Label: {0}\nBody: {1}", msg.Label, msg.Body);

    }
  }

}

以下の内容を makefile として保存します。

CSC = csc.exe

TARGETNAME=player1
SOURCE_FILE=player1.cs
REF=

OUTDIR=.\chk

all: "$(OUTDIR)\$(TARGETNAME).exe"


"$(OUTDIR)" :
  if not exist "$(OUTDIR)" mkdir "$(OUTDIR)"

CSC_OPT=\
  /nologo\
  /target:exe\
  /out:$(OUTDIR)\$(TARGETNAME).exe\
  /doc:$(OUTDIR)\$(TARGETNAME).xml\
  /debug+\
  /debug:full\
  /optimize-\
  /warn:4


$(OUTDIR)\$(TARGETNAME).exe: "$(OUTDIR)" $(SOURCE_FILE)
  $(CSC) $(CSC_OPT) $(REF) $(SOURCE_FILE)

上記、player1.cs と makefile を同じディレクトリに保存してください。 nmake のある、Visual Studio Command Prompt 等から nmake を実行してビルドしてください。

> nmake -a

Microsoft (R) Program Maintenance Utility Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.

  if not exist ".\chk" mkdir ".\chk"
  csc.exe  /nologo /target:exe /out:.\chk\player1.exe 
/doc:.\chk\player1.xml 
  /debug+ /debug:full /optimize- /warn:4  player1.cs

>

動作確認

  1. 上記で作成した recorder1.exe を実行する。

    すると上記で作成した、プライベートキュー MyTestQueue1 にメッセージがポストされたことが確認できる。



    メッセージのプロパティを見ると、確かにレコーダー・プログラム recorder1.exe から送信したメッセージであることが確認できる。

  2. 上記で作成した player1.exe を実行する。

    > player1.exe
    Label: Hello
    Body: This is a sample program.
    >
    
    確かにキューのメッセージが表示された。また、キューの画面を更新すると、キューからメッセージがなくなっていることも確認できる。

以上、この資料では C# から MQ を利用する方法について説明しました。