キューに置かれたメッセージングのトラブルシューティング

ここでは、Windows Communication Foundation (WCF) でのキューの使用に関する一般的な質問とトラブルシューティング ヘルプについて説明します。

一般的な質問

Q: WCF Beta 1 を使用しているときに MSMQ 修正プログラムをインストールしました。 この修正プログラムを削除する必要がありますか。

A: はい。 この修正プログラムのサポートは終了しています。 WCF は、現在、MSMQ で正常に動作しますので、修正プログラムは不要です。

Q: MSMQ 用のバインディングには、NetMsmqBindingMsmqIntegrationBinding の 2 つがあります。 それぞれの用途を教えてください。

A:NetMsmqBinding を使用するのは、2 つの WCF アプリケーション間でのキューを使用した通信にトランスポートとして MSMQ を使用する場合です。 また、MsmqIntegrationBinding を使用するのは、既存の MSMQ アプリケーションを使用して、新しい WCF アプリケーションと通信する場合です。

Q:NetMsmqBindingMsmqIntegration のバインディングを使用する際に、MSMQ をアップグレードする必要はありますか。

A: いいえ。 両方のバインディングを Windows XP と Windows Server 2003 上の MSMQ 3.0 で使用できます。 Windows Vista で MSMQ 4.0 にアップグレードすると、バインディングの特定の機能が使用可能になります。

Q:NetMsmqBindingMsmqIntegrationBinding のバインディングの機能のうち、MSMQ 4.0 では使用できるが MSMQ 3.0 では使用できないものはどれですか。

A: MSMQ 4.0 では使用できても MSMQ 3.0 では使用できない機能は次のとおりです。

  • カスタム配信不能キューは、MSMQ 4.0 でのみサポートされます。

  • MSMQ 3.0 と 4.0 では、有害メッセージの処理方法が異なります。

  • MSMQ 4.0 のみが、リモート トランザクション読み取りをサポートします。

Q: キューを使用する通信の一方の側で MSMQ 3.0 を使用し、もう一方の側で MSMQ 4.0 を使用することはできますか。

A: はい。

Q: 既存の MSMQ アプリケーションを新しい WCF クライアントまたはサーバーと統合しようと考えています。 使用している MSMQ インフラストラクチャの両方の側をアップグレードする必要がありますか。

A: いいえ。 どちら側も MSMQ 4.0 にアップグレードする必要はありません。

トラブルシューティング

ここでは、一般的なトラブルシューティングの問題に対する解答を示します。 既知の制限である一部の問題は、リリース ノートにも記載されています。

Q: プライベート キューを使用しようとすると、次の例外が表示されます: System.InvalidOperationException: この URL は無効です。 キューの URL に '$' 文字を使用することはできません。 net.msmq://machine/private/queueName の構文を使用して、プライベート キューをアドレス指定してください。

A: 構成とコードでキュー URI (Uniform Resource Identifier) を確認してください。 URI では、"$" 文字を使用できません。 たとえば、OrdersQueue という名前のプライベート キューのアドレスを指定する場合は、URI を net.msmq://localhost/private/ordersQueue と指定してください。

Q: キューに置かれたアプリケーションで ServiceHost.Open() を呼び出すと、"System.ArgumentException: ベース アドレスに URI クエリ文字列を含めることはできません" という例外がスローされます。 なぜですか?

A: 構成ファイルとコードでキュー URI を確認してください。 MSMQ のキューでは '?' 文字の使用がサポートされていますが、URI はこれを文字列クエリの開始と解釈します。 この問題を回避するには、'?' 文字を含まないキュー名を使用してください。

Q: 送信は成功したのですが、受信側でサービス操作が呼び出されません。 なぜですか?

A: 理由を特定するには、次のチェック リストを確認してください。

  • トランザクション キューの要件と指定済みの保証が適合することを確認します。 次の原則に注意してください。

    • "1 回限りの" 配信の保証 (ExactlyOnce = true) 付きの永続的なメッセージ (データグラムとセッション) は、トランザクション キューにのみ送信できます。

    • "1 回限りの" 配信の保証付きのセッションのみを送信できます。

    • セッションでトランザクション キューからメッセージを受け取るには、1 つのトランザクションが必要です。

    • 保証なし (ExactlyOnce = false) の一時的な、または永続的なメッセージ (ダイアグラムのみ) は、非トランザクション キューでのみ送受信できます。

  • 配信不能キューを確認します。 このキューにメッセージが置かれている場合は、メッセージが配信されなかった理由を特定してください。

  • 送信キューを確認して、接続性またはアドレス指定の問題を特定します。

Q: カスタム配信不能キューを指定したのですが、送信元アプリケーションを起動すると、カスタム配信不能キューが見つからない、または送信元アプリケーションにカスタム配信不能キューへのアクセス許可がないという例外が表示されます。 パフォーマンスが低下しているのはなぜですか。

A: カスタム配信不能キューの URI には、先頭のセグメントに "localhost" またはコンピューター名を含める必要があります。たとえば、net.msmq://localhost/private/myAppdead-letter queue のようにします。

Q: カスタム配信不能キューを常に定義する必要がありますか。それとも既定の配信不能キューがあるのですか。

A: 保証が "1 回限り" (ExactlyOnce = true) の場合、およびカスタム配信不能キューを指定していない場合は、システム全体のトランザクション配信不能キューが既定になります。

保証なし (ExactlyOnce = false) の場合、既定は配信不能キュー機能なしです。

Q: サービスにより、SvcHost.Open で "ListenerFactory が EndpointListener の要件を満たすことができません" という内容のメッセージがスローされます。 なぜでしょうか。

A. サービス コントラクトを確認してください。 "IsOneWay=true" をすべてのサービス操作に配置するのを忘れた可能性があります。 キューは、一方向のサービス操作しかサポートしません。

Q: キューにメッセージが置かれているのにサービス操作が呼び出されません。 問題は何ですか?

A: サービス ホストがエラーになっているかどうかを確認してください。 確認するには、トレースを調べるか、IErrorHandler を実装します。 既定では、有害メッセージが検出された場合、サービス ホストはエラーになります。

Q: キューにメッセージが格納されているのに、Web ホスト型のキューを使用するサービスがアクティブになりません。 なぜですか?

A: 最も一般的な理由はアクセス許可です。

  1. NetMsmqActivator プロセスが実行され、そのキューで、NetMsmqActivator の ID に読み取りおよびシーク アクセス許可が割り当てられていることを確認してください。

  2. NetMsmqActivator がリモート コンピューター上のキューを監視している場合は、NetMsmqActivator が制限付きトークンの下で実行されていないことを確認してください。 無制限のトークンを使用して NetMsmqActivator を実行するには、以下を実行します。

    sc sidtype NetMsmqActivator unrestricted
    

セキュリティ関連以外の Web ホストの問題については、「キューに置かれたアプリケーションの Web ホスト」を参照してください。

Q: 最も簡単にセッションにアクセスする方法を教えてください。

A: セッションの最後のメッセージに対応する操作で AutoComplete=true を設定し、残りのすべてのサービス操作で AutoComplete=false を設定します。

Q: キューを使用するセッション メッセージとキューを使用するデータグラム メッセージの両方を格納するキューから読み取るときに、サービスによって ProtocolException がスローされるのはなぜですか。

A: キューを使用するセッション メッセージとキューを使用するデータグラム メッセージは、それぞれ構成する方法が基本的に異なります。 このため、キューを使用するセッション メッセージを読み取ろうとするサービスは、キューを使用するデータグラム メッセージを受信できず、キューを使用するデータグラム メッセージを読み取ろうとするサービスは、セッション メッセージを受信できません。 これら両方の種類のメッセージを同じキューから読み取ろうとすると、次の例外がスローされます。

System.ServiceModel.MsmqPoisonMessageException: The transport channel detected a poison message. This occurred because the message exceeded the maximum number of delivery attempts or because the channel detected a fundamental problem with the message. The inner exception may contain additional information.
---> System.ServiceModel.ProtocolException: An incoming MSMQ message contained invalid or unexpected .NET Message Framing information in its body. The message cannot be received. Ensure that the sender is using a compatible service contract with a matching SessionMode.

アプリケーションが同じコンピューターからキューを使用するセッション メッセージとキューを使用するデータグラム メッセージの両方を送信する場合は、任意のカスタム配信不能キューだけでなくシステム配信不能キューで特にこの問題が発生する可能性があります。 メッセージを正常に送信できない場合、メッセージは配信不能キューに移されます。 このような場合は、セッション メッセージとデータグラム メッセージの両方が配信不能キューに置かれる可能性があります。 実行時にキューから読み取るときに両方の種類のメッセージを分離することはできません。そのため、アプリケーションでは、キューを使用するセッション メッセージとキューを使用するデータグラム メッセージの両方を同じコンピューターから送信しないでください。

MSMQ 統合 : 固有のトラブルシューティング

Q: メッセージを送信したり、サービス ホストを開いたりすると、スキームが不正であるというエラー メッセージが表示されます。 なぜですか?

A: MSMQ 統合バインディングを使用するときは、msmq.formatname スキームを使用する必要があります。 たとえば、msmq.formatname:DIRECT=OS:.\private$\OrdersQueue などです。 ただし、カスタム配信不能キューを指定するときは、net.msmq スキームを使用する必要があります。

Q: 公開または専用の形式名を使用して、Windows Vista 上のサービス ホストを開くと、エラーが発生します。 なぜですか?

A: Windows Vista 上の WCF 統合チャネルでは、メイン アプリケーション キューの有害メッセージ処理用のサブキューを開くことができるかどうかが確認されます。 サブキューの名前は、リスナーに渡される msmq.formatname URI から派生します。 MSMQ でのサブキュー名は、直接形式名に限定されます。 そのためにエラーが発生します。 キュー URI を直接形式名に変更してください。

Q: MSMQ アプリケーションからメッセージを受信すると、メッセージはキューに置かれ、受信側の WCF アプリケーションでは読み取られません。 なぜですか?

A: メッセージに本文があるかどうか確認してください。 メッセージに本文がない場合、MSMQ 統合チャネルはメッセージを無視します。 例外を通知する IErrorHandler を実装し、トレースを確認してください。

Q: ワークグループ モードで既定のバインディングを使用するサンプルを実行すると、メッセージは送信されるようですが、受信側で受信されません。

A: 既定では、メッセージには、Active Directory ディレクトリ サービスを必要とする MSMQ の内部証明書を使用して署名されます。 ワークグループ モードでは、Active Directory が使用できないため、メッセージに署名できません。 そのため、メッセージは配信不能キューに置かれ、"署名が正しくありません" などのエラーの原因が示されます。

この問題を回避するには、セキュリティを無効にします。 それには、ワークグループ モードで動作するように Mode = None を設定します。

また、MsmqTransportSecurity プロパティから Transport を取得し、それを Certificate に設定して、クライアント証明書を設定する方法もあります。

さらに、MSMQ と Active Directory 統合をインストールして回避することもできます。

Q: Active Directory で既定のバインディング (トランスポート セキュリティが有効) を使用してメッセージをキューに送信すると、"内部証明書が見つからない" という内容のメッセージが表示されます。 これをどのように修正すればよいですか?

A: これは、送信側の Active Directory 内の証明書を更新する必要があることを意味します。 それには、 [コントロール パネル][管理ツール][コンピューターの管理] の順に開き、 [MSMQ] を右クリックして [プロパティ] を選択します。 [ユーザー証明書] タブをクリックし、 [更新] ボタンをクリックします。

Q:Certificate を使用してメッセージを送信するときに、使用する証明書を指定すると、"証明書が無効" という内容のメッセージが表示されます。 これをどのように修正すればよいですか?

A: 証明書モードでは、ローカル コンピューターの証明書ストアを使用できません。 証明書スナップインを使用して、コンピューターの証明書ストアから現在のユーザー ストアに証明書をコピーする必要があります。 証明書スナップインを開くには、以下を実行します。

  1. [スタート] ボタンをクリックして [ファイル名を指定して実行] を選び、「mmc」と入力して [OK] をクリックします。

  2. [Microsoft 管理コンソール][ファイル] メニューを開き、 [スナップインの追加と削除] を選択します。

  3. [スナップインの追加と削除] ダイアログ ボックスで、 [追加] ボタンをクリックします。

  4. [スタンドアロン スナップインの追加] ダイアログ ボックスで証明書を選択し、 [追加] をクリックします。

  5. [証明書スナップイン] ダイアログ ボックスで、 [ユーザー アカウント] を選択し、 [完了] をクリックします。

  6. 次に、前の手順に従って 2 番目の証明書スナップインを追加しますが、今回は、 [コンピューター アカウント] を選択して [次へ] をクリックします。

  7. [ローカル コンピューター] を選択して [完了] をクリックします。 これで、コンピューターの証明書ストアから現在のユーザー ストアに証明書をドラッグ アンド ドロップできます。

Q: ワークグループ モードで、サービスによって別のコンピューター上のキューから読み取られるときに "access denied" 例外が発生します。

A: ワークグループ モードにおいて、リモート アプリケーションでキューへのアクセスを取得するには、アプリケーションにキューへのアクセス許可が必要です。 キューのアクセス制御リスト (ACL) に "匿名ログイン" を追加して、読み取りアクセス許可を割り当てます。

Q: ネットワーク サービス クライアント (またはドメイン アカウントを持たない任意のクライアント) でキューを使用するメッセージを送信すると、証明書が無効であるというエラー メッセージが表示され、送信できません。 これをどのように修正すればよいですか?

A: バインディング構成を確認してください。 既定のバインディングでは、メッセージに署名するために MSMQ トランスポート セキュリティを有効にしています。 これを無効にしてください。

リモート トランザクション受信

Q: マシン A にキューがあるときに、マシン B のキューからメッセージを読み取る WCF サービスを実行すると (リモート トランザクション受信シナリオ)、キューからメッセージが読み取られません。 トレース情報には、"Transaction cannot be imported." というメッセージが示され、受信に失敗したことがわかります。この問題を解決するには、どうすればいいですか。

A: これには、次の 3 つの理由が考えられます。

  • ドメイン モードの場合、リモート トランザクション受信には、Microsoft 分散トランザクション コーディネーター (MSDTC) ネットワーク アクセスが必要です。 これは、 [Windows コンポーネントの追加と削除] を使用して有効にできます。

    ネットワーク DTC アクセスの有効化を示すスクリーンショット。

  • トランザクション マネージャーと通信するための認証モードを確認します。 ワークグループ モードの場合は、[認証を必要としない] を選択する必要があります。 ドメイン モードの場合は、[相互認証を必要とする] を選択する必要があります。

    XA トランザクションの有効化

  • MSDTC が [インターネット接続ファイアウォール] 設定の例外の一覧に含まれていることを確認します。

  • Windows Vista を使用していることを確認します。 Windows Vista 上の MSMQ では、リモート トランザクション読み取りがサポートされています。 以前の Windows リリース上の MSMQ は、リモート トランザクション読み取りをサポートしません。

Q: キューから読み取るサービスが、Web ホストなどでのネットワーク サービスであるときにキューから読み取ると、アクセス拒否例外が発生するのはなぜですか。

A: ネットワーク サービス読み取りアクセスをキュー ACL に追加して、ネットワーク サービスがキューから読み取れるようにしてください。

Q: MSMQ アクティベーション サービスを使用して、リモート マシン上のキュー内のメッセージに基づいてアプリケーションをアクティブ化することは可能ですか。

A: はい。 これには、ネットワーク サービスとして動作するように MSMQ アクティベーション サービスを構成し、リモート コンピューター上のキューへのネットワーク サービス アクセスを追加する必要があります。

ReceiveContext を有効にしたカスタム MSMQ バインディングの使用

ネイティブの MSMQ では非同期の ReceiveContext 受信の I/O 完了がサポートされないため、ReceiveContext を有効にしてカスタム MSMQ バインディングを使用すると、着信メッセージの処理にスレッド プール内のスレッドが使用されます。 これは、このようなメッセージの処理に ReceiveContext の内部トランザクションが使用され、MSMQ では非同期処理がサポートされないためです。 この問題を回避するには、SynchronousReceiveBehavior をエンドポイントに追加して同期処理を強制するか、MaxPendingReceives を 1 に設定します。