9

メッセージを受信するとリモートシステムにsshできるJMSクライアントがあります(そして、そこでさまざまなことを行います-質問には関係ありません)。できるだけ早く処理する必要がある数百のそのようなメッセージが短期間に到着する可能性があります。

ただし、メッセージを受信したときに特定のリモート システムが使用できない可能性もあるため、後ほど (たとえば、1 時間ほど) 延期する必要があります。最善の解決策は、「遅延」値を設定してメッセージをキューに戻すことです。これにより、JMS ブローカは 1 時間以内にメッセージを再配信しないように指示されます。

よくないこと: 受信スレッドでスリープし、1 時間後に起動します。メッセージ コンシューマ プールは制限されているため (たとえば、8 つの接続が利用可能)、到達できないシステムが 8 つあると、処理全体が不必要にブロックされ、受け入れられません。

このような「遅延」値のメッセージまたはキュー自体の設定が見つかりませんでした。存在しますか?

回避策は、到達不能なシステムへのメッセージを格納するために 2 番目のキューを使用し、これらを個別に処理することです。しかし、これはあまり洗練されたソリューションではなく、追加のプログラミングが必要です。おそらくもっと良い方法があります。

4

6 に答える 6

9

JMS 2.0 仕様では、クライアントが送信する各メッセージの配信遅延値をミリ秒単位で指定できる「配信遅延」が定義されています。この値は、メッセージの配信遅延とそれが送信される GMT の合計であるメッセージ配信時間を定義します (トランザクション送信の場合、これはトランザクションがコミットされた時間ではなく、クライアントがメッセージを送信する時間です)。

メッセージの配信時間とは、JMS プロバイダーがメッセージをターゲット送り先で表示し、コンシューマーに配信できるようにする最も早い時間です。プロバイダーは、配信時間に達する前にメッセージを配信してはなりません。

この機能は、上記のシナリオで非常に便利です。

于 2014-04-25T06:06:41.380 に答える
4

このような状況では、コンテナー管理トランザクションが使用されます。onMessageメソッドがコンテナーによって呼び出されるとトランザクションが開始され、メソッドがonMessage正常に終了するとコミットされます (RuntimeException がスローされるかsetRollBackOnly、MessageDrivenBean コンテキストから呼び出されるとトランザクションは失敗します)。また、再配信間隔と再配信の最大数を構成することもできます。

Glassfish サーバーで OpenMQ を使用している場合は、これを ejb-jar.xml 記述子内で構成できます。ejb-jar.xml 記述子内で、プロパティ endpointExceptionRedeliveryInterval (ミリ秒単位) および endpointExceptionRedeliveryAttempts (メッセージがデッド メッセージ キューに送信される前に再配信される回数) を設定します。次に例を示します。

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar  xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
    version="3.1">    
    <enterprise-beans>
        <message-driven>
            <ejb-name>EjbName</ejb-name>
            <ejb-class>com.example.MyMessageDrivenBean</ejb-class>
            <messaging-type>javax.jms.MessageListener</messaging-type>
            <transaction-type>Container</transaction-type>
            <activation-config>
                <activation-config-property>
                    <activation-config-property-name>destination</activation-config-property-name>
                    <activation-config-property-value>someQueue</activation-config-property-value>
                </activation-config-property>
                <activation-config-property>
                   <activation-config-property-name>destinationType</activation-config-property-name>
                   <activation-config-property-value>javax.jms.Queue</activation-config-property-value>
                </activation-config-property>

                <activation-config-property>
                    <activation-config-property-name>endpointExceptionRedeliveryInterval</activation-config-property-name>
                    <activation-config-property-value>5000</activation-config-property-value>
                </activation-config-property>
                <activation-config-property>
                    <activation-config-property-name>endpointExceptionRedeliveryAttempts</activation-config-property-name>
                    <activation-config-property-value>4</activation-config-property-value>
                </activation-config-property>
            </activation-config>
        </message-driven>
    </enterprise-beans>
</ejb-jar>

メッセージ駆動型 Bean 内では、RuntimeException をスローして失敗としてマークし、メッセージはキューに返されます。

WebLogic Server の構成プロパティもここにあります: http://docs.oracle.com/cd/E12839_01/apirefs.1111/e13952/pagehelp/JMSjmstemplatesjmstemplateconfigredeliverytitle.html

于 2013-05-22T08:30:52.407 に答える
3

これは、JMS 2.0 より前の JMS API では不可能です。原則として、メッセージ トランスポートはメッセージをできるだけ速く配信するように最適化されており、任意の間隔で再配信するためにメッセージを保持するスケジューラがありません。そのような機能を持つトランスポート プロバイダーが存在すると仮定すると、コードは JMS に準拠している可能性がありますが、アプリ自体はこのベンダー固有の動作に依存するため、記述したものはすべてそのトランスポート プロバイダーにバインドされます。

JMS 2.0 をサポートする MQ のバージョンに適用される回答については、@Shashi の回答を参照してください。

于 2010-08-09T19:23:23.133 に答える
0

私はこの問題を次のように考えます: jms メッセージ コンシューマ プールは利用可能ですが、一部のバックエンド リソース (つまり ssh) はメッセージの完了を許可するために利用できません。

それに同意する場合、消費を完了できないため、消費者プールが利用可能である理由は何ですか? プールが利用できない場合、メッセージはキューに積み上げられます....利用可能になるまで...そして、利用可能になったら続行しても問題ありませんでした。その場合は、リソースが利用可能かどうかに応じて、プールを開始/停止するための監視コンポーネントが必要です。1 時間待つ必要はありませんが、バックエンドが利用できない場合に限ります。最後に jms はすべてですが、監視ツールではありません。

于 2014-04-24T22:38:00.760 に答える