5

私の現在のプロジェクトでは、多くの宛先 (数百から 20 または 30k まで) からのメッセージを消費する必要があります。すべての宛先はトピックです。現在(初期負荷テストの場合)、すべてのメッセージは同じサーバーのスレッド プールにローカルに作成されます。

私の現在の春の設定は、共通の TaskExecutor を持つブローカー (クラスタリング用) と DefaultMessageListenerContainers (DMLC) のネットワークに埋め込まれた activemq を使用します。宛先の数は非常に多くなりますが、各宛先のスループットは比較的低くなります。

私の唯一の要件は、すべてのメッセージができるだけ早く消費されることです。

私の設定:

<bean id="connectionfactory" class="org.springframework.jms.connection.CachingConnectionFactory" destroy-method="destroy">
    <property name="targetConnectionFactory">
        <ref bean="amqConnectionFactory" />
    </property>
</bean>
<bean id="amqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
    <property name="brokerURL" value="vm://localhost:61616?async=false&amp;jms.dispatchAsync=false" />
    <property name="userName" value="admin" />
    <property name="password" value="admin" />
</bean>
<bean id="listenerThreadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="70" />
    <property name="maxPoolSize" value="70" />
    <property name="daemon" value="true" />
    <property name="keepAliveSeconds" value="60" />
</bean>

<!-- Message Listener Container Template for Topics -->
<bean id="topiccontainertemplate" class="org.springframework.jms.listener.DefaultMessageListenerContainer" scope="prototype"
    destroy-method="destroy">
    <property name="autoStartup" value="false" />
    <property name="connectionFactory" ref="connectionfactory" />
    <property name="pubSubDomain" value="true" />
    <property name="cacheLevelName" value="CACHE_CONSUMER" />
    <property name="destinationName" value="default" />
    <property name="maxMessagesPerTask" value="1" />
    <property name="receiveTimeout" value="1" />
    <property name="taskExecutor" ref="listenerThreadPoolTaskExecutor" />
</bean>

私のコードはアプリケーション コンテキストを DMLC-Factory として使用し、コンテナーの最終的な構成を設定します。

    AbstractMessageListenerContainer container = context.getBean("simpletopiccontainertemplate", AbstractMessageListenerContainer.class);
    container.setDestinationName(localEntity.getId().getDestination());
    container.setMessageListener(mylistener);
    container.start();

この構成ではメッセージが失われることはありませんが、個々のメッセージの移行時間は非常に長くなる可能性があります。

Q1:多数の目的地を聞くためのより効率的な方法はありますか?

Q2:リスナーの構成を改善できる可能性はありますか?

Q3: DMLC のほかに、SimpleMessageListenerContainer も試しましたが、機能しませんでした。私の設定に何か問題がありますか?

<bean id="simpletopiccontainertemplate" class="org.springframework.jms.listener.SimpleMessageListenerContainer" scope="prototype"
    destroy-method="destroy">
    <property name="autoStartup" value="false" />
    <property name="connectionFactory" ref="connectionfactory" />
    <property name="destinationName" value="default" />
    <property name="concurrency" value="1" />
    <property name="pubSubDomain" value="true" />
    <property name="taskExecutor" ref="listenerThreadPoolTaskExecutor" />
</bean>
4

2 に答える 2

5

2 万から 3万の を手動で作成SimpleMessageListenerContainerし、それぞれが異なるトピックをリッスンしていることを正しく理解していますか? すべてのリスナーがデフォルトで 1 つのスレッドを作成し、1 つの JVM で同時に実行される 20 ~ 30,000 のスレッドが印象的 (かつ恐ろしい) であるため、それが機能することにも驚いています。

パフォーマンスを向上させる方法は 2 つあります。

  • JmsTemplate.receive()便利な方法などを使用して、メッセージを手動で読む。非常に短いタイムアウトを使用することを忘れないでください。より少ないスレッド (10? 100?) ですべてのトピックを繰り返しチェックすることで、ある程度の遅延が発生しますが、スレッドが少ないということは、コンテキストの切り替えに費やされる時間が少なくなることを意味します。

    正直なところ、このソリューションがスケーリングしてパフォーマンスを向上させるとは思いませんが、さまざまな数のスレッドとタイムアウトを調べてみてください。

  • 集まる!残念ながら、1 つのアプリケーションで 20 ~ 30k のトピックを聞くことは決してうまくいきません (十分に高速です)。ただし、このタスクを簡単にスケールアウトできるようです。10 またはおそらく 100 のサーバーを投入し、それぞれに 2000 または 200 のトピックをリッスンさせます。これは直線的にスケーリングします。

于 2012-06-08T19:25:20.730 に答える
1

からに移動しDefaultMessageListenerContainerましたSimpleMessageListenerContainer。単純なコンテナはプッシュメッセージングを使用します。このように(そして適切な設定で、組み込みブローカーは宛先をポーリングする代わりにメッセージをリスナーにプッシュします。

于 2012-06-13T11:46:18.857 に答える