Websphere MQメッセージを削除せずに閲覧するにはどうすればよいですか?
-
22-07-2019 - |
質問
Websphere MQキューにメッセージをポストし、その後応答のために別のキューをポーリングする.NET Windows Formsアプリケーションを作成しています。応答が返された場合、アプリケーションはリアルタイムで部分的に応答を処理します。ただし、応答はキューにとどまる必要があるため、応答キューからも読み取る毎日のバッチジョブが残りの処理を実行できます。
メッセージを読む限り、私は得ました。私が理解できなかったのは、それを削除せずに読む方法です。
これまでに得たものは次のとおりです。私はMQ初心者なので、提案は歓迎します。また、C#でお気軽にご返信ください。
Public Function GetMessage(ByVal msgID As String) As MQMessage
Dim q = ConnectToResponseQueue()
Dim msg As New MQMessage()
Dim getOpts As New MQGetMessageOptions()
Dim runThru = Now.AddMilliseconds(CInt(ConfigurationManager.AppSettings("responseTimeoutMS")))
System.Threading.Thread.Sleep(1000) 'Wait for one second before checking for the first response'
While True
Try
q.Get(msg, getOpts)
Return msg
Catch ex As MQException When ex.Reason = MQC.MQRC_NO_MSG_AVAILABLE
If Now > runThru Then Throw ex
System.Threading.Thread.Sleep(3000)
Finally
q.Close()
End Try
End While
Return Nothing 'Should never reach here'
End Function
注:コードが実際にメッセージを削除することを確認していません。しかし、それが私がMQが機能することを理解する方法です。デフォルトの動作でない場合は修正してください。
解決
MQOO_BROWSEオプションでキューを開く必要があります。次に、最初の読み取り時に、MQGMO_BROWSE_FIRSTオプションを使用してGETを実行します。最後に、後続のGETでMQGMO_BROWSE_NEXTオプションを使用する必要があります。
注:MQOOはMQオープンオプションであり、MQGMOはMQ Get Messageオプションです。
他のヒント
実際には、個別のキューでこれを行う必要があります。 End of Day処理には独自のキューが必要です。メッセージの一部を処理した後、EODキューに送信します。
[参照]オプションを使用すると、既にどこで処理したメッセージを追跡する必要があります。
また、GETで待機タイムアウトを設定できます。したがって、「キューをチェックする前に1秒待つ」必要はありません。今書いているように、メッセージ取得オプションでNOWAITを設定していないため、メッセージなしの条件をヒットすることはできません。
後世のために、マンボキングとjmucchielloの回答に基づいた方法の大幅に改善されたバージョンを次に示します。
Public Function GetMessage(ByVal correlID As Byte()) As MQMessage
Dim waitInterval = CInt(ConfigurationManager.AppSettings("responseTimeoutMS"))
Dim q As MQQueue = Nothing
Try
Dim msg As New MQMessage()
Dim getOpts As New MQGetMessageOptions()
q = ConnectToResponseQueue()
msg.MessageId = MQC.MQMI_NONE
msg.CorrelationId = correlID
getOpts.MatchOptions = MQC.MQMO_MATCH_CORREL_ID
getOpts.WaitInterval = waitInterval
getOpts.Options = MQC.MQGMO_BROWSE_FIRST Or MQC.MQGMO_WAIT
q.Get(msg, getOpts)
Return msg
Finally
If q IsNot Nothing AndAlso q.IsOpen() Then q.Close()
End Try
End Function
この議論に少し遅れて来ていることに気付きました。おそらく、このアプリはすでにコーディングされているでしょう。変更する必要がある場合、または同様のことを行う必要があるかもしれない他の人のために、いくつかの観察があります。
まず、v7 QMgrとv7 WMQクライアントでこれを行うことができる場合、これが推奨されるソリューションです。 v7では、.NetサポートがSupportPacからベース製品の一部に移動されました。かなりの新機能、いくつかのバグ修正、パフォーマンスの向上があります。また、v7ではpub-sub ...を使用できます。これにより、2番目の観察結果が得られます。
元の投稿の説明に基づいて、Pub-Subでこれを行っていました。メッセージを配置するアプリは、配置するだけで済み、トピックに配置されていることを知る必要さえありません。実際には、メッセージプロデューサーへのキューのように見えるトピックにエイリアスを設定できます。消費するアプリは、サブスクライブするか、2つの管理サブスクリプションを作成して、公開されたメッセージが指定した2つのキューに送られるようにします。その場合、アプリにはそれぞれ専用のキューがあり、プロデューサーとバッチアプリのコーディングの変更は一切必要ありません。設定のみです。もちろん、トランザクションを駆動するアプリは、メッセージを閲覧するのではなく、実際にメッセージを消費する必要があります。
ここでの利点はいくつかあります:
- キューがメッセージでいっぱいになると、インデックス作成がディスクにフラッシュされ、しきい値を超えると、重大なパフォーマンスヒットが発生します。したがって、現在の方法ではそれほどうまくスケーリングできません。
- pub-subメソッドを使用すると、リアルタイムアプリまたはバッチアプリ、あるいはその両方の複数のインスタンスを使用でき、これらは同じまたは異なるQMgr上に存在できます。スケールアップは簡単です。
- 同じQMgr上にある必要があるリアルタイムアプリとバッチアプリ間の依存関係を排除します。
- より透明な管理。リアルタイムキューにメッセージが蓄積されている場合は、問題があることがわかります。
ここでもまったく異なる問題がいくつかあります。これらの1つは、静止オプションの場合に失敗を使用することです。これの目的は、QMgrが完全にシャットダウンされると、QMgrがシャットダウンされたことを示す戻りコードでAPI呼び出しが終了することです。このオプションを含めない場合、2つ以上の接続されたアプリでQMgrが完全にシャットダウンすることはなく、強制的にシャットダウンするか、プロセスをブルートフォースで強制終了する必要があります。原則として、それをサポートするすべてのAPI呼び出しで静止する場合は、常に失敗を使用します。存在する理由は、XAトランザクション性を必要とする人々のためですが、何らかの理由でそれを使用できません。このシナリオでは、CONNECTおよび最初のGETまたはPUT呼び出しは、セットを静止し、後続のGETまたはPUT操作が使用しない場合、Failを使用します。これにより、QMgrはGET / PUTコールのセット全体が完了するまで待機しますが、次のCONNECTまたはGET / PUTは静止時に失敗を使用するため、QMgrは必要に応じてシャットダウンすることができます。
ここでの他の観察は、ここのコードにはキャッチがないということです。私はコールスタックのさらに上の範囲に1つがあると推測していますか?根本原因を突き止めることができるように、例外からのWMQリターンコードを常に出力することをお勧めします。コンサルティングエンゲージメントでは、リターンコード(またはJMS / XMSコードのリンクされた例外)の印刷に失敗すると、アプリのプロダクションへの昇格を妨げるべきであるとクライアントに常にアドバイスします。それは本当に重要です。 getMessage()を呼び出すコードに問題がある場合でも、ここでサンプルコードスニペットを再利用する人は、この重要な部分が欠落していることに気付かない可能性があります。