キューに置かれたメッセージングのトラブルシューティング
ここでは、Windows Communication Foundation (WCF) でのキューの使用に関する一般的な質問とトラブルシューティング ヘルプについて説明します。
一般的な質問
Q: WCF Beta 1 を使用しているときに MSMQ 修正プログラムをインストールしました。 この修正プログラムを削除する必要がありますか。
A: はい。 この修正プログラムのサポートは終了しています。 WCF は、現在、MSMQ で正常に動作しますので、修正プログラムは不要です。
Q: MSMQ 用のバインディングには、NetMsmqBinding と MsmqIntegrationBinding の 2 つがあります。 それぞれの用途を教えてください。
A:NetMsmqBinding を使用するのは、2 つの WCF アプリケーション間でのキューを使用した通信にトランスポートとして MSMQ を使用する場合です。 また、MsmqIntegrationBinding を使用するのは、既存の MSMQ アプリケーションを使用して、新しい WCF アプリケーションと通信する場合です。
Q:NetMsmqBinding と MsmqIntegration
のバインディングを使用する際に、MSMQ をアップグレードする必要はありますか。
A: いいえ。 両方のバインディングを Windows XP と Windows Server 2003 上の MSMQ 3.0 で使用できます。 Windows Vista で MSMQ 4.0 にアップグレードすると、バインディングの特定の機能が使用可能になります。
Q:NetMsmqBinding と MsmqIntegrationBinding のバインディングの機能のうち、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: 最も一般的な理由はアクセス許可です。
NetMsmqActivator
プロセスが実行され、そのキューで、NetMsmqActivator
の ID に読み取りおよびシーク アクセス許可が割り当てられていることを確認してください。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: 証明書モードでは、ローカル コンピューターの証明書ストアを使用できません。 証明書スナップインを使用して、コンピューターの証明書ストアから現在のユーザー ストアに証明書をコピーする必要があります。 証明書スナップインを開くには、以下を実行します。
[スタート] ボタンをクリックして [ファイル名を指定して実行] を選び、「
mmc
」と入力して [OK] をクリックします。[Microsoft 管理コンソール] の [ファイル] メニューを開き、 [スナップインの追加と削除] を選択します。
[スナップインの追加と削除] ダイアログ ボックスで、 [追加] ボタンをクリックします。
[スタンドアロン スナップインの追加] ダイアログ ボックスで証明書を選択し、 [追加] をクリックします。
[証明書スナップイン] ダイアログ ボックスで、 [ユーザー アカウント] を選択し、 [完了] をクリックします。
次に、前の手順に従って 2 番目の証明書スナップインを追加しますが、今回は、 [コンピューター アカウント] を選択して [次へ] をクリックします。
[ローカル コンピューター] を選択して [完了] をクリックします。 これで、コンピューターの証明書ストアから現在のユーザー ストアに証明書をドラッグ アンド ドロップできます。
Q: ワークグループ モードで、サービスによって別のコンピューター上のキューから読み取られるときに "access denied" 例外が発生します。
A: ワークグループ モードにおいて、リモート アプリケーションでキューへのアクセスを取得するには、アプリケーションにキューへのアクセス許可が必要です。 キューのアクセス制御リスト (ACL) に "匿名ログイン" を追加して、読み取りアクセス許可を割り当てます。
Q: ネットワーク サービス クライアント (またはドメイン アカウントを持たない任意のクライアント) でキューを使用するメッセージを送信すると、証明書が無効であるというエラー メッセージが表示され、送信できません。 これをどのように修正すればよいですか?
A: バインディング構成を確認してください。 既定のバインディングでは、メッセージに署名するために MSMQ トランスポート セキュリティを有効にしています。 これを無効にしてください。
リモート トランザクション受信
Q: マシン A にキューがあるときに、マシン B のキューからメッセージを読み取る WCF サービスを実行すると (リモート トランザクション受信シナリオ)、キューからメッセージが読み取られません。 トレース情報には、"Transaction cannot be imported." というメッセージが示され、受信に失敗したことがわかります。この問題を解決するには、どうすればいいですか。
A: これには、次の 3 つの理由が考えられます。
ドメイン モードの場合、リモート トランザクション受信には、Microsoft 分散トランザクション コーディネーター (MSDTC) ネットワーク アクセスが必要です。 これは、 [Windows コンポーネントの追加と削除] を使用して有効にできます。
トランザクション マネージャーと通信するための認証モードを確認します。 ワークグループ モードの場合は、[認証を必要としない] を選択する必要があります。 ドメイン モードの場合は、[相互認証を必要とする] を選択する必要があります。
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 に設定します。