Previous spoke confirmation message is sent, this time to talk about the news consumption patterns confirm
Confirmation message is sent to confirm that the switch and send a message to confirm the queue, the message is to confirm the consumer to confirm whether the message is normally consumed by consumers!
There are three modes acknowledgment message
- AcknowledgeMode.NONE: Automatic confirmation
- AcknowledgeMode.AUTO: confirmation under the circumstances
- AcknowledgeMode.MANUAL: manual confirmation
Manual confirmation is programmer control of one of the highest mode, automatic confirmation message is sent to the consumer after the news was confirmed, and delete the message if the consumer an error in the implementation process, will still result in the loss of the message. The second model will be based on the implementation of the consumer to decide whether to throw exceptions confirm or deny so on.
Paste the code of practice
Because I was the producer and consumer in two separate projects, and then I found
spring.rabbitmq.listener.simple.acknowledge-mode = manual
This configuration requires configuration on both sides, otherwise it will not turn on manual confirmation mode!
@Component public class Publisher { @Autowired private RabbitTemplate rabbitTemplate; public void send(){ String message = "mck learn rabbitmq"; User user = new User(); user.setName("mck"); user.setAge(25); user.setSex("男"); MessagePostProcessor messagePostProcessor = new MessagePostProcessor() { @Override public Message postProcessMessage(Message message) throws AmqpException { message.getMessageProperties().setHeader("error","mck"); return message; } }; rabbitTemplate.convertAndSend("hello",user,messagePostProcessor); } }
@Component public class Receiver { @RabbitHandler @RabbitListener(queues = "hello") public void process(@Payload User user, Channel channel, @Headers Map<String,Object> map){ System.out.println(user.getName()); if (map.get("errorrr")!= null){ System.out.println("错误的消息"); try { channel.basicNack((Long)map.get(AmqpHeaders.DELIVERY_TAG),false,true); //否认消息 return; } catch (IOException e) { e.printStackTrace(); } } try { channel.basicAck((Long)map.get(AmqpHeaders.DELIVERY_TAG),false); //确认消息 } catch (IOException e) { e.printStackTrace(); } } }
After several tests found that, if turned on after manual confirmation mode, the message did not confirm it, consumers will continue to spend the next message, just like the previous article we talked about, broker in two parts, one part is to be message, in part, has been sent, but did not receive a confirmation message.
We can see in the console, which is part of unacked has been sent, but did not receive a confirmation message. At this time, if you consumer forced to close, that is, that he is disconnected, then the message will re-enter the queue ready to go, when you restart the consumer, you will receive this message again! ! ! !
We can see in the consumer code manually nack messages, which means nack message telling broker, this good news I did not consume, re-queued and over again, and then re-enter is ready, go again is consumer spending. Besides can also reject message,
channel.basicReject((Long)map.get(AmqpHeaders.DELIVERY_TAG),false); 这样处理的消息就会直接丢失掉!!!