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<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - unknown delivery tag 1, class-id=60, method-id=80)
这个问题还有一个表现就是rabbitmq控制台上 channel菜单中括号中的数字不断增大,据查资料说每个connection最多有2000多个channel,再多了会被累死,所以这个问题还是需要解决的,修改之前,rabbitmq控制台截图:
可以看到这个数字是很大的啊,
修改之前的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控制台:
这事,再查看java运行日志,也不再报错,谨以本菜鸟踩过的坑跟大家分享,参照博客: