This article is participating in the Java Theme Month – Java Debug Notes Event, see the event link for details
The problem
I used RabbitMq message middleware for enterprise wechat group messaging. The code of the consumer side is as follows. If there is an exception when consuming, it looks like there is no problem.
@Component @RabbitListener(queues = "cn.thinkjoy.wxcenter.article") public class WxArticleSendBusiness { private Logger logger = LoggerFactory.getLogger(WxArticleSendBusiness.class); @rabbithandler public void receive(String json){logger.info(" MQ received message :{}",json); try{ if(json! =null){// service handler}}catch (Exception e){{logger.info("MQ failed to send message "); e.printStackTrace(); }}}}Copy the code
Let’s take a look at message confirmation on the consumer side of RabbitMq. RabbitMq provides message confirmation. When a consumer declares a queue, it can specify a noAck parameter, and when noAck=false RabbitMQ will wait for an ACK signal from the consumer before removing the message from memory (and disk, if persistent).
RabbitMQ does not set a timeout for unack messages, and the only way it can determine whether the message needs to be redelivered to the consumer is if the consumer who consumed the message has been disconnected. The reason for this is that RabbitMQ allows consumers to consume a message for a very long time. The problem is that if the message is abnormal and I do not display the call noAck=false, and MY consumer is always online, then I will repeatedly consume the abnormal message, has been printing the abnormal message log!
An exception occurs is a test message calls on Friday, lead to consumer when an exception is thrown, and the message is a test of other department calls the message body, next Monday, I received the test server hard disk capacity is insufficient, the use of more than 90% space, I turn on the log, goodfellas test environment a total of 50 g hard drive is almost full, I opened the RabbitMQ consumption log and found that the error log kept being printed and repeated. My first thought was that the producer had been sending the wrong message body for the scheduled task. I cleared the log and asked the developer if they had sent the message only once on Friday and no scheduled task had been sent. At that time I did not know how to consume RabbitMQ, and finally in order to understand RabbitMQ to eat RabbitMQ field guide this is later, so know that there is no exception processing need to display call notification MQ to remove abnormal messages from MQ, the code is as follows:
@Component @RabbitListener(queues = "cn.thinkjoy.wxcenter.article") public class WxArticleSendBusiness { @RabbitHandler Public void receive(String JSON, Channel Channel, Message Message) throws IOException {logger.info(" MQ received Message :{}", json); try { if (json ! = null) {// service handler}} catch (Exception e) {logger.info("mq received message Exception: "+e); e.getStackTrace(); channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); }}}Copy the code
When abnormal shows call channel. BasicAck (message. GetMessageProperties (.) getDeliveryTag (), false); DeliveryTag is the serial number of the message sent by Chanel. Each Channel maintains a set of unconfirm message serial number. Every publish a data, the element in the set is added by 1, and the handleAck method is called every time. The unconfirm collection deletes one (multiple=false) or multiple (multiple=true) entries accordingly.
conclusion
This bug was pretty serious at the time, but I wrote hydrology!!