为什么我的 RabbitMQ 通道不断关闭?
我正在调试一些使用 Apache POI 从 Microsoft Office 文档中提取数据的 Java 代码。有时,它会遇到大文档,POI 会在内存不足时崩溃。此时,它会尝试将错误发布到 RabbitMQ,以便其他组件知道此步骤失败并采取适当的操作。但是,当它尝试发布到队列时,它会收到 com.rabbitmq.client.AlreadyClosedException(干净连接关闭;原因:尝试使用关闭通道)
。
这是错误处理程序代码:
try {
//Extraction and indexing code
}
catch(Throwable t) {
// Something went wrong! We'll publish the error and then move on with
// our lives
System.out.println("Error received when indexing message: ");
t.printStackTrace();
System.out.println();
String error = PrintExc.format(t);
message.put("error", error);
if(mime == null) {
mime = "application/vnd.unknown";
}
message.put("mime", mime);
publish("IndexFailure", "", MessageProperties.PERSISTENT_BASIC, message);
}
为了完整起见,这里是发布方法:
private void publish(String exch, String route,
AMQP.BasicProperties props, Map<String, Object> message) throws Exception{
chan.basicPublish(exch, route, props,
JSONValue.toJSONString(message).getBytes());
}
我在 try 块中找不到任何关闭 RabbitMQ 通道的代码。是否存在可以隐式关闭通道的情况?
编辑:我应该注意到 AlreadyClosedException 是由发布内的 basicPublish
调用引发的。
I'm debugging some Java code that uses Apache POI to pull data out of Microsoft Office documents. Occasionally, it encounter a large document and POI crashes when it runs out of memory. At that point, it tries to publish the error to RabbitMQ, so that other components can know that this step failed and take the appropriate actions. However, when it tries to publish to the queue, it gets a com.rabbitmq.client.AlreadyClosedException (clean connection shutdown; reason: Attempt to use closed channel)
.
Here's the error handler code:
try {
//Extraction and indexing code
}
catch(Throwable t) {
// Something went wrong! We'll publish the error and then move on with
// our lives
System.out.println("Error received when indexing message: ");
t.printStackTrace();
System.out.println();
String error = PrintExc.format(t);
message.put("error", error);
if(mime == null) {
mime = "application/vnd.unknown";
}
message.put("mime", mime);
publish("IndexFailure", "", MessageProperties.PERSISTENT_BASIC, message);
}
For completeness, here's the publish method:
private void publish(String exch, String route,
AMQP.BasicProperties props, Map<String, Object> message) throws Exception{
chan.basicPublish(exch, route, props,
JSONValue.toJSONString(message).getBytes());
}
I can't find any code within the try block that appears to close the RabbitMQ channel. Are there any circumstances in which the channel could be closed implicitly?
EDIT: I should note that the AlreadyClosedException is thrown by the basicPublish
call inside publish.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
对于那些想知道为什么他们的消费通道关闭的人,请检查您是否多次尝试确认或拒绝交付。
在rabbitmq日志中你会看到如下消息:
For those who wonder why their consuming channels are closing, check if you try to Ack or Nack a delivery more than once.
In the rabbitmq log you would see messages like:
我也遇到了这个问题。我的情况的原因是,首先我使用 Durable = false 构建了队列,并且在日志文件中,当我将 Durable 切换为 true 时,我收到了此错误消息:
然后,我更改了队列的名称,它对我有用。我假设 RabbitMQ 服务器将构建队列的记录保存在某处,并且它无法将状态从持久更改为非-durable,反之亦然。
我再次为新队列设置了durable=false,这次我得到了这个错误。
我的假设是正确的。当我通过以下方式列出rabbitMQ服务器中的队列时:
我在服务器中看到了两个队列。
总而言之,有两种解决方案:
1.重命名队列的名称这不是一个好的解决方案
2.通过以下方式重置rabbitMQ:
I also had this problem. The reason for my case was that, first I built the queue with durable = false and in the log file I had this error message when I switched durable to true:
Then, I changed the name of the queue and it worked for me. I assumed that the RabbitMQ server keeps the record of the built queues somewhere and it cannot change the status from durable to non-durable and vice versa.
Again I made durable=false for the new queue and this time I got this error
My assumption was true. When I listed the queues in rabbitMQ server by:
I saw both queues in the server.
To summarize, 2 solutions are:
1. renaming the name of the queue which is not a good solution
2. resetting rabbitMQ by:
AMQP 通道因通道错误而关闭。可能导致通道错误的两种常见情况:
我会研究设置在您尝试使用的通道上启动 ShutdownListener 使用 addShutdownListener() 捕获关闭事件并查看导致的原因 它。
An AMQP channel is closed on a channel error. Two common things that can cause a channel error:
I would look into setting up a ShutdownListener on the channel you're trying to use to publish a message using the addShutdownListener() to catch the shutdown event and look at what caused it.
就我而言,另一个原因是我错误地确认了一条消息两次。这会导致第二次确认后日志中出现这样的 RabbitMQ 错误。
在我删除重复的确认后,错误消失了,通道不再关闭,并且 AlreadyClosedException 也消失了。
Another reason in my case was that by mistake I acknowledged a message twice. This lead to RabbitMQ errors in the log like this after the second acknowledgment.
After I removed the duplicate acknowledgement then the errors went away and the channel did not close anymore and also the AlreadyClosedException were gone.
我想为将搜索此主题的其他用户添加此信息
接收通道关闭异常的另一个可能原因是当发布者和消费者使用不同的队列声明/设置从 RabbitMQ 站点访问通道
队列
/
时
I'd like to add this information for other users who will be searching for this topic
Another possible reason for Receiving a Channel Closed Exception is when Publishers and Consumers are accessing Channel/Queue with different queue declaration/settings
Publisher
Worker
From RabbitMQ Site
显然,AMQP 连接和/或通道突然关闭的原因有很多。就我而言,队列中有太多未确认的消息,因为消费者没有指定 prefetch_count< /a> 因此连接每约 1 分钟就会终止一次。通过将消费者的预取计数设置为非零值来限制未确认消息的数量解决了该问题。
Apparently, there are many reasons for the AMQP connection and/or channels to close abruptly. In my case, there was too many unacknowledged messages on the queue because the consumer didn't specify the prefetch_count so the connection was getting terminated every ~1min. Limiting the number of unacknowledged messages by setting the consumer's prefetch count to a non-zero value fixed the problem.