springboot集成RabbitMq异常 Channel shutdown: channel error; protocol method

2020-01-07 11:09:51,843 [AMQP Connection 127.0.0.1:5672] ERROR o.s.a.r.c.CachingConnectionFactory -[CachingConnectionFactory.java:1567]- Channel shutdown: channel error; protocol method: #method(reply-code=406, reply-text=PRECONDITION_FAILED - unknown delivery tag 1, class-id=60, method-id=80)

这个问题还有一个表现就是rabbitmq控制台上 channel菜单中括号中的数字不断增大,据查资料说每个connection最多有2000多个channel,再多了会被累死,所以这个问题还是需要解决的,修改之前,rabbitmq控制台截图:

springboot集成RabbitMq异常 Channel shutdown: channel error; protocol method_第1张图片

可以看到这个数字是很大的啊,

修改之前的application.yml

  rabbitmq:
    #host: 192.168.1.204
    host: 127.0.0.1
    port: 5672
    username: xj-ipc
    password: xj-ipc 
    virtual-host: /

对于这个问题的分析:

package com.boot.security.server.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeoutException;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.springframework.stereotype.Controller;

import com.boot.security.server.utils.CMDUtil;
import com.boot.security.server.utils.FileUtil;
import com.rabbitmq.client.Channel;


/**
 * Created by qs5 on 2018/11/11.
 * @author wangzhen
 */
@Controller
public class MsgReceiverController {
	private static final Logger log = LoggerFactory.getLogger("adminLogger");

    private static MsgReceiverController rabbitConsumer;
    @Resource
    private WebSocketController webSocketServerEndpoint; //引入WebSocket
    
	@Autowired
	private FileUtil fileUtil;
		    
    /**
     * 构造方法注入rabbitTemplate
     */
    @PostConstruct
    public void init() {
        rabbitConsumer = this;
        rabbitConsumer.webSocketServerEndpoint = webSocketServerEndpoint;
    }
    private static Logger logger = LoggerFactory.getLogger("adminLogger");
    
    // 设备系统实时状态
    @RabbitListener(queues = "XJ-DCU-IPC")    
    @RabbitHandler
    public void receiver(String content, Message message, Channel channel)throws IOException{
        // 确认消息已接收
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        logger.info("----------------XJ-DCU-IPC--------------------"+content);
        // 发送给WebSocket 由WebSocket推送给前端
        rabbitConsumer.webSocketServerEndpoint.sendMessageOnline(content);
        try {
			channel.close();
		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			log.error(e.toString());
			e.printStackTrace();
		}
	}
    
    // 运行日志实时
    @SuppressWarnings("static-access")
	@RabbitListener(queues = "XJ-DCU-IPC-LOG")    
    @RabbitHandler
    public void logReceiver(String content, Message message, Channel channel)throws IOException{
    	channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    	logger.info("----------------XJ-DCU-IPC-LOG--------------------"+content);
    	Date date = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");  
		String date1 = formatter.format(date);
    	String filename = "log_" + date1 + ".log";
    	int pos = 0;
    	// 插入日志文件
    	fileUtil.insert(filename, pos, content);
    	// 确认消息已接收
    	// 消息的标识,false只确认当前一个消息收到,true确认所有consumer获得的消息
        try {
			channel.close();
		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			log.error(e.toString());
			e.printStackTrace();
		}
    }
    
    // 异常日志实时
    @SuppressWarnings("static-access")
	@RabbitListener(queues = "XJ-DCU-IPC-EXCEPTION-LOG")    
    @RabbitHandler
    public void exLogReceiver(String content, Message message, Channel channel)throws IOException{
    	channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    	logger.info("----------------XJ-DCU-IPC-EXCEPTION-LOG--------------------"+content);
    	Date date = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");  
		String date1 = formatter.format(date);
    	String filename = "exLog_" + date1 + ".log";
    	int pos = 0;
    	// 插入日志文件
    	fileUtil.insert(filename, pos, content);
    	// 确认消息已接收
    	// 消息的标识,false只确认当前一个消息收到,true确认所有consumer获得的消息
        try {
			channel.close();
		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			log.error(e.toString());
			e.printStackTrace();
		}
    }
}

        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
有一个手动确认的操作,而spring-boot-starter-amqp默认是自动签收信息的方式,

查资料看到一个说发生这种情况是 double ack问题 我也似懂非的,大概意思就是消费结果签收了两次,我们代码里面是写的手动签收,但是系统还有一次自动
签收,所以就想到了是不是需要配置一下让rabbitmq手动签署,就不会触发自动签收的功能勒

于是我就将rabbitmq配置文件配置成了手动签收,再去测试的时候就不会报这个异常信息啦
修改后application.yml

  rabbitmq:
    #host: 192.168.1.204
    host: 127.0.0.1
    port: 5672
    username: xj-ipc
    password: xj-ipc 
    virtual-host: /
    listener:
      simple:
        concurrency: 1
        max-concurrency: 1
        acknowledge-mode: manual
        prefetch: 1 

修改后,rabbitmq控制台:

 

springboot集成RabbitMq异常 Channel shutdown: channel error; protocol method_第2张图片

这事,再查看java运行日志,也不再报错,谨以本菜鸟踩过的坑跟大家分享,参照博客:

https://blog.csdn.net/qq_38082304/article/details/103049696

你可能感兴趣的:(springboot集成RabbitMq异常 Channel shutdown: channel error; protocol method)