我发现了许多" Broken Pipe"或"连接被拒绝"使用RabbitMQ Java驱动程序amqp-client
版本5.1.2
在我的应用程序中出错。 RabbitMQ服务器版本为3.7.3
。
要限制收到的消息,我只需将Thread.sleep(2000)
循环放入DefaultConsumer
autoAck=0
。channel.basicQos(..)
。当然,我可以设置java.net.SocketException
,但我需要的不仅仅是"我目前有多少消息"。
但是,此伪代码会导致// register new connection
// register new channel / consumer for receiving messages which waits for 2 seconds on each handleDelivery
// sleep for 60 seconds (main-thread) and let the consumer do its job
// register new channel (for writing)
:
handleDelivery
另一种情况是,在java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)
at java.net.SocketOutputStream.write(SocketOutputStream.java:153)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
at java.io.DataOutputStream.flush(DataOutputStream.java:123)
at com.rabbitmq.client.impl.SocketFrameHandler.flush(SocketFrameHandler.java:177)
at com.rabbitmq.client.impl.AMQConnection.flush(AMQConnection.java:559)
at com.rabbitmq.client.impl.AMQCommand.transmit(AMQCommand.java:127)
at com.rabbitmq.client.impl.AMQChannel.quiescingTransmit(AMQChannel.java:447)
at com.rabbitmq.client.impl.AMQChannel.quiescingTransmit(AMQChannel.java:429)
at com.rabbitmq.client.impl.AMQChannel.quiescingRpc(AMQChannel.java:346)
at com.rabbitmq.client.impl.AMQChannel.rpc(AMQChannel.java:337)
at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:277)
at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:138)
at com.rabbitmq.client.impl.ChannelN.open(ChannelN.java:133)
at com.rabbitmq.client.impl.ChannelManager.createChannel(ChannelManager.java:176)
at com.rabbitmq.client.impl.AMQConnection.createChannel(AMQConnection.java:542)
at com.rabbitmq.client.impl.recovery.AutorecoveringConnection.createChannel(AutorecoveringConnection.java:108)
at myapp.rabbitmq.RabbitMQPool.registerChannel(RabbitMQPool.java:232)
at myapp.rabbitmq.RabbitMQPool.registerChannel(RabbitMQPool.java:200)
at myapp.rabbitmq.RabbitMQPool.registerWriteOnlyChannel(RabbitMQPool.java:185)
at myapp.rabbitmq.RabbitMQPool.registerWriteOnlyChannel(RabbitMQPool.java:181)
at myapp.MyMainClass.start(MyMainClass.java:110)
at myapp.MyMainClass.main(MyMainClass.java:46)
中休眠几分钟后,连接被重置/损坏管道/等等。但是让我们专注于伪代码的第一种情况。
这会在创建第二个通道时导致以下堆栈跟踪,第二个通道也使用第一个连接。
handleDelivery
但是,如果我不在每个ConnectionFactory factory = new ConnectionFactory();
factory.setPort(5672);
factory.setHost("xxx.xxx.xxx.xxx");
factory.setUsername("user");
factory.setPassword("pass");
factory.setAutomaticRecoveryEnabled(true);
factory.setConnectionTimeout(0);
Connection connection = factory.newConnection();
等待2秒,那么创建第二个队列就会很好。为什么呢?
这些是用于创建新连接的参数:
if (!connection.isOpen()) {
// this fires at the second time when first channel consumes with `Thread.sleep(2000)`
}
channel = connection.createChannel();
channel.queueDeclare(channelName, true, false, false, null);
if (consumer != null) { // only the first time
DefaultConsumer queueingConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
Thread.sleep(2000)
}
... some more @Overrides
};
channel.basicConsume(channelName, autoAck, queueingConsumer);
}
构建频道的代码:
3.5.6
RabbitMQ服务器日志不会显示任何错误,也不会抛出其他错误。 RabbitMQ通过局域网连接,我在两种配置中都会将错误重现几十次,结果相同。
我从驱动程序版本5.1.2
升级到3.5.6
,RabbitMQ服务器(也是新的操作系统)从3.7.3
升级到QueueingConsumer
,问题就开始了。我想也许DefaultConsumer
被弃用了,现在我必须使用$orders = Order::where([
'kitchen_status' => 1,
'delivery_status' => 0,])->orderBy('update_at','DESC')->paginate(15);
。
答案 0 :(得分:0)
我想我找到了解决方案。
将消费线程与Thread.sleep(...)
暂停似乎并不是一个好主意。
当我在频道上使用basicCancel(...)
时,一切运作良好,不会关闭任何频道,也不会引发异常。