我正在尝试使用Java中的RabbitMQ运行一个非常基本的应用程序。我很容易使用Java ExecutorService
同时使用消息。我的项目是使用Spring,所以我已经定义了我的ThreadPoolExecutorFactoryBean
:
<bean class="org.springframework.scheduling.concurrent.ThreadPoolExecutorFactoryBean"
destroy-method="destroy">
<property name="corePoolSize" value="8"/>
<property name="keepAliveSeconds" value="600"/>
<property name="maxPoolSize" value="16"/>
<property name="threadGroupName" value="CallbackQueue-Group"/>
<property name="threadNamePrefix" value="CallbackQueue-Worker-"/>
</bean>
我正在使用这样做的类将这个bean注入我的主mesasge队列:
this.connection = getConnectionFactory().newConnection(getQueueExecutor());
this.channel = this.connection.createChannel();
this.channel.queueDeclare(getQueueName(), true, false, false, null);
this.channel.basicConsume(getQueueName(), false, new DefaultConsumer(this.channel) {
@Override public void handleDelivery(String consumerTag, Envelope envelope,
BasicProperties properties, byte[] body) throws IOException {
logger.debug("Received message {}", properties.getCorrelationId());
try { Thread.sleep(3000); } catch (InterruptedException e) {};
getChannel().basicAck(envelope.getDeliveryTag(), false);
}
});
简单地说,当我向队列发布多个消息时,我应该看到日志语句发生得非常接近,即使任务需要一段时间才能执行。但是,我看到我的消费者一次只处理一个任务,尽管ExecutorService
!甚至更奇怪的是,我实际上看到池中的不同线程服务队列,虽然从来没有在同一时间:
12:43:40.650 [CallbackQueue-Worker-2] DEBUG MyApplication - Received message 65bfbba29b4965eb0674c082c73dad7c
12:43:43.737 [CallbackQueue-Worker-3] DEBUG MyApplication - Received message 2a0b29012b13857c5a0ae8060f66dbaa
12:43:46.755 [CallbackQueue-Worker-3] DEBUG MyApplication - Received message 3c0742f9a284ac9c6b602200254c70db
12:43:49.769 [CallbackQueue-Worker-3] DEBUG MyApplication - Received message a462236fab19d51ba4bfea1582410a64
12:43:52.783 [CallbackQueue-Worker-3] DEBUG MyApplication - Received message 1a4713e1066dfc9e4ec1302098450a1f
我在这里做错了什么?我的ThreadPoolExecutorFactoryBean
或我的RabbitMQ代码中是否有一些其他配置?
答案 0 :(得分:1)
来自com.rabbitmq.client.Channel的描述:
虽然多个线程可以使用Channel,但重要的是 确保只有一个线程一次执行命令。同时 执行命令可能会导致UnexpectedFrameError 抛出。
这可能是个原因吗?您的日志显示使用了不同的工作人员(我们看到2和3),但一次只能使用一名工人。