RabbitMQ实战指南,线程池报错,消息未消费完全,从多线程中理解问题原因clean channel shutdown; protocol method: channel.close

RabbitMQ实战指南,线程池报错,消息未消费完全

详细出错信息

**com.rabbitmq.client.ShutdownSignalException: clean channel shutdown; protocol method: #method<channel.close>(reply-code=200, reply-text=Closed due to exception from Consumer (amq.ctag-SIvdR7UthqyEgn0us8H_XA) method handleDelivery for channel AMQChannel(amqp://), class-id=0, method-id=0)
**

15:08:28.363 [pool-1-thread-3] ERROR com.rabbitmq.client.impl.ForgivingExceptionHandler - Consumer com.zzf.rabbitmq.amqpclient.RabbitConsumer$1@53639c56 (amq.ctag-SIvdR7UthqyEgn0us8H_XA) method handleDelivery for channel AMQChannel(xxx) threw an exception for channel AMQChannel(xxxx)
com.rabbitmq.client.AlreadyClosedException: channel is already closed due to clean channel shutdown; protocol method: #method<channel.close>(reply-code=200, reply-text=OK, class-id=0, method-id=0)
	at com.rabbitmq.client.impl.AMQChannel.ensureIsOpen(AMQChannel.java:258)
	at com.rabbitmq.client.impl.AMQChannel.transmit(AMQChannel.java:427)
	at com.rabbitmq.client.impl.AMQChannel.transmit(AMQChannel.java:421)
	at com.rabbitmq.client.impl.recovery.RecoveryAwareChannelN.basicAck(RecoveryAwareChannelN.java:93)
	at com.rabbitmq.client.impl.recovery.AutorecoveringChannel.basicAck(AutorecoveringChannel.java:428)
	at com.zzf.rabbitmq.amqpclient.RabbitConsumer$1.handleDelivery(RabbitConsumer.java:39)
	at com.rabbitmq.client.impl.ConsumerDispatcher$5.run(ConsumerDispatcher.java:149)
	at com.rabbitmq.client.impl.ConsumerWorkService$WorkPoolRunnable.run(ConsumerWorkService.java:104)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
消费端消息: Hello RabbitMq4
Exception in thread "main" com.rabbitmq.client.ShutdownSignalException: clean channel shutdown; protocol method: #method<channel.close>(reply-code=200, reply-text=Closed due to exception from Consumer (amq.ctag-SIvdR7UthqyEgn0us8H_XA) method handleDelivery for channel AMQChannel(xxxxx), class-id=0, method-id=0)
	at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:66)
	at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:36)
	at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:502)
	at com.rabbitmq.client.impl.ChannelN.close(ChannelN.java:622)
	at com.rabbitmq.client.impl.ChannelN.close(ChannelN.java:547)
	at com.rabbitmq.client.impl.ChannelN.close(ChannelN.java:540)
	at com.rabbitmq.client.impl.recovery.AutorecoveringChannel.close(AutorecoveringChannel.java:73)
	at com.zzf.rabbitmq.amqpclient.RabbitConsumer.main(RabbitConsumer.java:45)
Caused by: com.rabbitmq.client.ShutdownSignalException: clean channel shutdown; protocol method: #method<channel.close>(reply-code=200, reply-text=Closed due to exception from Consumer (amq.ctag-SIvdR7UthqyEgn0us8H_XA) method handleDelivery for channel AMQChannel(xxxxx), class-id=0, method-id=0)
	at com.rabbitmq.client.impl.ChannelN.close(ChannelN.java:594)
	at com.rabbitmq.client.impl.ChannelN.close(ChannelN.java:547)
	at com.rabbitmq.client.impl.StrictExceptionHandler.handleChannelKiller(StrictExceptionHandler.java:72)
	at com.rabbitmq.client.impl.StrictExceptionHandler.handleConsumerException(StrictExceptionHandler.java:61)
	at com.rabbitmq.client.impl.ConsumerDispatcher$5.run(ConsumerDispatcher.java:154)
	at com.rabbitmq.client.impl.ConsumerWorkService$WorkPoolRunnable.run(ConsumerWorkService.java:104)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
15:08:28.386 [AMQP Connection0000:5672] INFO com.rabbitmq.client.impl.AMQConnection - Received a frame on an unknown channel, ignoring it

解决办法

把消费者的睡眠时间延长 TimeUnit.SECONDS.sleep(10);
把时间设置为10秒,20秒,实在不行100秒

public class RabbitConsumer {


    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
       ........
        TimeUnit.SECONDS.sleep(10);
        channel.close();
        connection.close();
    }
}

背景

出现这个问题,是在看RabbitMQ实战指南的第一章生产和消费消息实例中出现的。其实这也不能完全算一个问题。主要原因就是我们的channel和connection已经被关闭了,肯定就消费不了消息了。我们是需要晚一点关闭这两个东西就行。
也就是多休眠几秒

TimeUnit.SECONDS.sleep(10);
熟悉多线程的朋友应该会知道,这个是休眠的代码,主要就是休眠10秒后,我们再关闭资源,这是主线程的逻辑。

这个时候会出现问题,也就是子线程,队列里面的消息在休眠10秒的时间里,子线程没有消费完,所以报错。

我们加上一些debug调试一下
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
	System.out.println("消费端消息: " + new String(body));
	System.out.println(Thread.currentThread().getName() + "子线程在消费消息");
	try {
		TimeUnit.SECONDS.sleep(1);
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
	channel.basicAck(envelope.getDeliveryTag(),false);
	}
};
channel.basicConsume(QUEUE_NAME,consumer);
 //等待回调函数执行完毕,关闭资源
TimeUnit.SECONDS.sleep(5);
System.out.println(Thread.currentThread().getName() + "主线程即将关闭");
channel.close();
connection.close();

现象

在这里插入图片描述

发布了33 篇原创文章 · 获赞 15 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_35764460/article/details/104460868