4

システムで activemq を使用していますが、次のメッセージが表示されます。 0%) またはメモリ使用量 (100%) の制限に達し、メッセージ add() をブロックしてリソースの解放を保留しています。

これは、私が正しく理解している場合、プロデューサーが高速であるのに対し、コンシューマーが遅いためです。その結果、消費者がメッセージを読み取ってメモリを解放するまで、最終的にプロデューサーがブロックされます。私が望むのは、プロデューサーがブロックされていないことと、メモリがいっぱいになると古いメッセージが破棄されることです。

私が読んだことを理解すると、次の構成でうまくいくはずです (messageEvictionStrategy、pendingMessageLimitStrategy) が、うまくいかず、理由がわかりません。

テスト上の理由から問題をより迅速に表示するために、低いメモリ使用量制限を低 (35Mb) に指定しましたが、問題が発生したときに activemq が古いメッセージを単にドロップする必要がある場合があります。

ActiveMQConnectionFactory useAsyncSend=true に設定し、sendTimeout を指定するという、満足できない解決策を 1 つ見つけました。これにより、プロデューサはブロックされなくなりますが、このようにして、最も古いメッセージではなく、最新のメッセージがドロップされます。

最後に、私は非永続的なトピックについて話しています。

助けてくれる人なら誰でも完璧です。以下にactivemq構成があります

        <destinationPolicy>
        <policyMap>
            <policyEntries>
                <policyEntry topic=">" producerFlowControl="false" memoryLimit="35 Mb">
               <pendingSubscriberPolicy>
                   <vmCursor />
                </pendingSubscriberPolicy>
                    <messageEvictionStrategy>
                        <oldestMessageEvictionStrategy/>
                    </messageEvictionStrategy>
                    <pendingMessageLimitStrategy>
                        <constantPendingMessageLimitStrategy limit="10"/>
                    </pendingMessageLimitStrategy>
                </policyEntry>
            </policyEntries>
        </policyMap>
    </destinationPolicy>

    <systemUsage>
        <systemUsage sendFailIfNoSpace="true">
            <memoryUsage>
                <memoryUsage limit="35 mb"/>
            </memoryUsage>
            <storeUsage>
                <storeUsage limit="1 gb"/>
            </storeUsage>
            <tempUsage>
                <tempUsage limit="5000 mb"/>
            </tempUsage>
        </systemUsage>
    </systemUsage>  

activemq バージョン 5.7.0

私は春のテンプレートを使用してメッセージを送信します:

    <bean class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="pooledJmsConnectionFactory"/>
    <property name="timeToLive" value="100"/>
</bean>

比較的小さいサイズの javax.jms.ObjectMessage を送信します。

アプリケーションに多くのトピックがありますが、ローカルに 1 つのスレッドからノンストップ メッセージを常に同じトピックに送信することで、問題を再現することができました。送信されたメッセージは単なる小さな文字列でした。

プロデューサは 1 つしかありませんが、遅いコンシューマが 1 つ (または複数) あると問題が発生するようですが、遅いコンシューマは 1 つあれば十分です。遅い消費者が存在しない場合、問題は発生しません。

私はそれが何の違いもないと思いますが、私は使用します

       <transportConnectors>
       <transportConnector name="openwire" uri="nio://0.0.0.0:33029?wireFormat.maxInactivityDuration=60000&amp;wireFormat.maxInactivityDurationInitalDelay=60000"/>
    </transportConnectors>
4

2 に答える 2

1

JmsTemplate を使用して非同期送信し、配信できないメッセージを送信する場合は、explicitQosEnabled を有効にして deliveryMode=1 (非永続) に設定する必要があります。また、クライアント側では、コンシューマーのプリフェッチ制限を小さくする必要があります

サーバ

<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="pooledJmsConnectionFactory"/>
    <property name="explicitQosEnabled" value="true"/>
    <property name="deliveryMode" value="1"/>
</bean>

クライアント

<jms:listener-container .. prefetch="1000">
...
</jms:listener-container>

理由を聞かないでください...しかし、これで問題が解決したようです。基本的に100%必要ではありませんが、誰かが私にこれを説明できれば完璧です

于 2013-11-12T08:40:42.677 に答える