When contacting RammitMQ, many articles said to set properties in the configuration
# rabbitmq configure rabbitmq: host: xxx.xxx.xxx.xxx port: xxxx username: xxx password: xxxxxx ## Producer Configuration # Enable release confirmation, which is the confirm mode. After the consumer ack answers, the message is deleted from the queue #The confirmation message has been sent to the queue (Queue) publisher-returns: true #The confirmation message has been sent to the exchange (Exchange) publisher-confirm-type: correlated listener: #Consumer configuration retry: enabled: true # Whether to support retry default -requeue-rejected: false max-attempts: 5 #Maximum number of retries initial-interval: 3000 # Retry interval direct: acknowledge-mode: manual simple: acknowledge-mode: manual
When the message fails to receive the message, it can be called repeatedly 5 times; according to this operation, it is found that there is no repeated call.
----------------------------------Correct Idea-------------- -------------------------------------------------- -----------------
After setting the properties of the configuration file, use redis and channel.basicNack in the code to save the error record to the database to facilitate finding the cause;
--------------------------------------- code
package com.charg.listener; import com.charg.common.constant.CacheConstants; import com.charg.common.constant.Constants; import com.charg.common.utils.JsonUtils; import com.charg.common.utils.redis.RedisUtils; import com.charg.constant.RabbitConstants; import com.charg.product.domain.bo.ProductDeviceBo; import com.charg.product.domain.bo.RabMsgLogBo; import com.charg.product.service.IProductDeviceService; import com.charg.product.service.IRabMsgLogService; import com.rabbitmq.client.Channel; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; 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 org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import java .io.IOException; import java.time.Duration; /** * rabbitmq listener */ @Slf4j @Component public class RabbitQueueListener { /** * maximum number of retries */ private static int maxReconsumeCount = 3; @Autowired private StringRedisTemplate redisTemplate ; */ /** * Listen to the processor of the queue * * @param message @RabbitListener(queues = "queue name") @RabbitHandler public void onMessage(Message message, Channel channel) { //Unique identifier String messageId = message.getMessageProperties().getMessageId() ; try { //Judge whether messageId exists in redis if (verificationMessageId(messageId)) { log.error("The message has been processed repeatedly, and refuse to receive it again..."); //Reject the message channel.basicReject(message.getMessageProperties ().getDeliveryTag(), false); } else {//Process the message if it does not exist // Receive the message if (StringUtils.isNotBlank(new String(message.getBody()))) { //Modify the business logic if (!false) { log.error("The message is about to return to the queue again for processing...logic error"); // handle the maximum number of callbacks getMaximumNumber(message, channel); / _ _ _ _ _ _ _ / Reject message channel.basicReject(message.getMessageProperties().getDeliveryTag(), false); } } * The maximum number of times to record messages } catch (Exception e) { e.printStackTrace(); try { if (message.getMessageProperties().getRedelivered()) { log.error("The message has been processed repeatedly, refused to receive again----..."); // reject the message channel.basicReject(message.getMessageProperties( ).getDeliveryTag(), false); } else { log.error("The message is about to return to the queue for processing..."); // handle the maximum number of callbacks getMaximumNumber(message, channel); } } catch (Exception exception) { exception.printStackTrace(); } } } /** * * @param message * @param channel * @throws IOException */ private void getMaximumNumber(Message message, Channel channel) { try { int recounsumeCounts = RedisUtils.getCacheObject("messageMaxKey"+message.getMessageProperties().getMessageId()) == null ? 0 : RedisUtils.getCacheObject("messageMaxKey"+message.getMessageProperties().getMessageId()); if (maxReconsumeCount > recounsumeCounts) { log.info("maxMessageId(message.getMessageProperties().getMessageId())=" + recounsumeCounts); channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true); // 记录重试次数 maxMessageId(message.getMessageProperties().getMessageId()); } /** } else { log.info("The number of times has reached three times---------" + RedisUtils.getCacheObject(CacheConstants.MESSAGE_MAX_KEY + message.getMessageProperties().getMessageId())); // Put the message back into the queue channel .basicNack(message.getMessageProperties().getDeliveryTag(), false, false); // Clear the cache RedisUtils.deleteObject("messageMaxKey" + message.getMessageProperties().getMessageId()); //After three retries, it still fails Need to log to the database addRabMsgLog(message); } } catch (Exception e) { e.printStackTrace(); } * Set the maximum number of retries for the message */ public void maxMessageId(String messageId) { String messageMax = "messageMaxKey"+ messageId; // Store in the cache to record how many times the message has been retried if (RedisUtils.hasKey(messageMax )) { RedisUtils.incrAtomicValue(messageMax); } else { //Wrong message - insert into the database RedisUtils.setCacheObject(messageMax, 1, Duration.ofHours(Constants.MESSAGE_TIME)); } } / ** * Verify whether the message is consumed Pass the message * * @param messageId message id * @return */ public boolean verificationMessageId(String messageId) { // Whether the message exists key String verifyIsExistKey = "messageExistKey" + messageId; if ((RedisUtils.hasKey(verifyIsExistKey))) { return true; } return false; } /** * Save the consumed message * * @param message message * @return */ public void addMessageId(Message message) { // store in cache RedisUtils.setCacheObject("messageExistKey" + message.getMessageProperties().getMessageId(), message.getMessageProperties().getMessageId(), 1); } / ** * message queue failed Log operation * own database logic */ public void addRabMsgLog(Message message) { log.info("====operation log==="); //Record the content to the database } } ------------------------- -------Database Table