2

RabbitMQ にメッセージを送信するための REST API を作成しており、チャネルを作成/閉じるためのベスト プラクティスを理解しようとしていました。RabbitMQ Java クライアント API を使用しています。

RabbitMQPublisherConnection現在、 RabbitMQ 接続をスプリング注入するクラスがあります。このクラスは、別のクラスにスプリング注入されRabbitMQPublisherChannelます。このクラスには、チャネルを作成する次の関数があります。

public class RabbitMQPublisherChannel {

public Channel createChannel(String amqpExchange,
                                         String exchangeType,
                                         String queue,
                                         String routingKey,
                                         boolean durableExchange,
                                         boolean durableQueue,
                                         boolean autoDelete,
                                         com.rabbitmq.client.Connection connection) throws IOException {
        Channel channel = null;
        channel = connection.createChannel();

        if ((amqpExchange != null) && !"".equals(amqpExchange.trim())) {
            if (log.isLoggable(Level.FINEST)) {
                log.finest("exchange:" + amqpExchange + ", type: " + exchangeType + ", durableExchange: " + durableExchange);
            }
            channel.exchangeDeclare(amqpExchange, exchangeType, durableExchange);
            channel.queueDeclare(queue, durableQueue, false, autoDelete, null);
            channel.queueBind(queue, amqpExchange, routingKey);
        }
        return channel;
    } }

RabbitMQPublisherこれで、 Spring Injectクラスの 3 番目のクラスが作成されましたRabbitMQPublisherChannel。私のアプリケーション コンテキストは次のようになります。

<bean id="rabbitMQPublisher" class="com.rabbitmq.RabbitMQPublisher">
    <property name="publisherChannel"     ref="rabbitMQPublisherChannel"/>
</bean>

<bean id="rabbitMQPublisherChannel" class="com.rabbitmq.RabbitMQPublisherChannel">
    <property name="publisherConnection"     ref="rabbitMQPublisherConnection"/>
</bean>

<bean id="rabbitMQPublisherConnection" class="com.rabbitmq.RabbitMQPublisherConnection">
    <property name="rabbitMQConnectionSettingMap">
        .. connection ..
    </property>
</bean>

このクラスRabbitMQPublisherには、RabbitMQ にメッセージを発行する機能があります。

public boolean publishMessage(String message, String queueName){

    try {
        // Validate queue name
        com.rabbitmq.client.Channel channel     = publisherChannel.getRabbitMQChannel(queueName);
        RabbitMQConnection          settings    = publisherChannel.getPublisherConnection().getRabbitMQConnectionSettingMap().get(queueName);

        if (channel != null) {
            channel.basicPublish(settings.getAmqpExchange(), settings.getAmqpRoutingKey(), null, message.getBytes());
            publisherChannel.closeChannel(channel);
        }
    } catch (AlreadyClosedException e) {
        return FAILURE_RESPONSE;
    } catch (IOException e) {
        return FAILURE_RESPONSE;
    }
    return SUCCESS_RESPONSE;
}

このアプリケーションは tomcat を介して実行されますが、AppDynamics でチャネルを閉じるのに、メッセージの発行にかかる合計時間の 47% がかかることに気付きました。チャネルを閉じる呼び出しを削除すると、この 47% の時間を 32 ミリ秒節約できますが、RabbitMQ 管理コンソールで、その接続のチャネル数が増加していることに気付きます。

だから私の質問は -

  1. tomcat が 1 秒あたり複数のリクエストを受け取ると仮定して、パブリッシュのたびにチャンネルを開閉するのは良い方法ですか?
  2. これは複数のスレッド間でチャネル プールを共有することをお勧めしますか ( RabbitMQ はこれを推奨していますが、次のようにも述べていますEven so, applications should prefer using a Channel per thread instead of sharing the same Channel across multiple threads.)。これは、スレッドごとに新しいチャネルを作成することを意味しますか?
  3. チャネルを閉じず、アイドル状態の RabbitMQ http api クリーンアップ チャネルを使用することをお勧めします。(これをお勧めしないでください)?
  4. 32ミリ秒節約する価値はありますか?

ありがとう

4

1 に答える 1

3

あなたは Spring Framework ユーザーなので、Spring AMQPの使用を検討してください。はRabbitTemplate、キャッシュされたチャネルを 1 つの接続で使用し、チャネルは操作ごとにキャッシュからチェックアウト (および返されます) されます。デフォルトのキャッシュ サイズは 1 であるため、一般的には自分のような環境に合わせて設定する必要があります。

于 2015-03-13T13:37:34.033 に答える