默認情況下,rabbitMQ消息隊列中的消息一旦有消費者接收了就會被刪除,假如這個時候消費者宕機了或者異常了,就可能會導致消息丟失(接收到消息了,但並沒有處理完這個消息),這時候就需要消費端在處理完消息後告訴rabbitMQ:“我已經成功消費完這個消息了,你可以刪除這個消息了”。
1.修改消費端rabbitmq配置信息,將消息確認機制設置爲手動確認,因爲默認是自動確認。
/**
* @XuJD
* @date 2019/4/15
*/
@Configuration
public class RabbitConfig {
@Value("${rabbitmq.et.url}")
private String url;
@Value("${rabbitmq.et.vhost}")
private String vhost;
@Value("${rabbitmq.et.exchange}")
private String exchange;
@Value("${rabbitmq.et.queue}")
private String queue;
@Value("${rabbitmq.et.username}")
private String username;
@Value("${rabbitmq.et.password}")
private String password;
@Value("${rabbitmq.ettask.routerkey}")
private String etTaskRouterKey;
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setAddresses(url);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
connectionFactory.setVirtualHost(vhost);
return connectionFactory;
}
@Bean
public Queue queue() {
return new Queue(queue,true);
}
@Bean
public TopicExchange exchange() {
return new TopicExchange(exchange);
}
@Bean
public Binding binding() {
return BindingBuilder.bind(queue()).to(exchange()).with(etTaskRouterKey);
}
@Bean
public SimpleMessageListenerContainer messageContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
container.setQueues(queue());
container.setChannelTransacted(true);
container.setMessageListener(SpringContextHolder.getBean(EtTaskListener.class));
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
return container;
}
}
這是RabbitMQ消費端完整的配置信息(僅供參考),配置消息手動確認就需要加上下面這句代碼就可以了
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
AcknowledgeMode是個枚舉類,有三個字段
NONE,//自動確認
MANUAL,//手動確認
AUTO;//視情況確認
- 接收消息,處理完消息後給rabbitMQ確認一下,確認之後rabbitMQ纔會將該消息從內存中刪除
public class EtTaskListener implements ChannelAwareMessageListener{
@Override
public void onMessage(Message message, Channel channel) throws Exception {
//消息處理邏輯代碼忽略。。。傳來的消息就在message中
Long tag = message.getMessageProperties().getDeliveryTag();
//向rabbitMQ確認消息已被消費,第一個參數tag是當前消息唯一標識ID,
//第二個參數false表示當前消息,true表示tag小於等於當前tag的所有消息
channel.basicAck(tag,false);
}
}