MQ高级
生产者重连
有的时候由于网络波动 可能导致客户端连接MQ失败的情况 这个时候可以进行重连设置 就是连接失败之后的重连机制
生产者确认
更侧重的是发送消息的时候 拥有publisher confirms 以及 publisher returns 两种确认机制 用于向生产者返回确认信息
- 消息投递到了MQ但是路由失败 比如没有找到对应的key 或者交换机根本没有绑定任何队列 这时会通过publisher returns 返回路由异常原因 也会返回ACK
- 临时消息投递到了mq 比如投递到了一个没有做 持久化的队列里面 会返回ACK
- 对于持久消息而言 投递到了一个做了持久化的队列里面 并且持久化成功了的话就会返回ACK
- 其他情况会但会NACK
spring AMQP 实现生产者确认
return机制一般是路由未匹配到 一般无需开启的
- 每一个rabbitTemplate 只能配置一个returncallback 可以通过aware接口对Template对象来setReturnCallBack 方法
@Configuration
public class RabbitConfig implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);
rabbitTemplate.setReturnCallback((message, replaycode, replayText, exchange, routintKey) -> {
System.out.println(message+";;;"+replaycode+";;;"+replayText+";;;;"+exchange+";;;"+routintKey);
});
}
}
- confirmcallback 只能在每一个消息发送的时候单独指定
@GetMapping("/send/{message}")
@ResponseBody
public String sendMessage(@PathVariable String message) {
CorrelationData cd = new CorrelationData(UUID.randomUUID().toString());
cd.getFuture().addCallback(new ListenableFutureCallback<CorrelationData.Confirm>() {
@Override
public void onFailure(Throwable ex) {
log.error("消息投递错了");
System.out.println("你好 消息失败了");
}
@Override
public void onSuccess(CorrelationData.Confirm result) {
log.error("消息投递成功");
System.out.println("消息发送成功");
if(result.isAck()){
System.out.println("消息收到ACK");
}else{
System.out.println("你好 收到NACK"+result.getReason());}
}
});
rabbitTemplate.convertAndSend("directExchange","L3OL",message+UUID.randomUUID().toString(),cd);
//rabbitTemplate.convertAndSend("object.queue", (Object) (message + UUID.randomUUID().toString()),cd);
return "hello,MQ!"+message;
}
就是在发送消息的时候绑定一个回调如果消息返回NACK的话就 做一个重新发送的处理以保证一个消息投递的可靠性
MQ的可靠性
消费者的可靠性
消费者确认机制
- spring amqp 实现的消费者确认机制
- 失败自动重试 可以在listener侧做一个失败重试 防止消息一异常就返回到MQ
- 失败消息策略处理
重试耗尽后,将失败消息投递到指定的交换机步骤
消费者如何保证消息一定被消费?
业务幂等性
唯一消息ID
幂等这个概念 可以从消息重复消费来处理 也可以从业务来判断 就是允许消息的重复消费 但是业务方法 比如减库存 支付 等做幂等处理
面试题 -- 如何保证支付服务和交易服务之间订单状态的一致性?
终极拷打 -- 如果交易服务消息处理失败 有没有什么兜底方案?
延迟消息
延迟消息概念:生产者发送一个消息指定一个时间,消费者不会立即收到消息,而是在指定时间之后再收到消息
死信交换机
- 死信交换机工作方式 以及实现延迟消息
延迟消息插件
取消超时订单
大部分订单 都会尽快支付 如果每个订单的延迟消息一直在MQ中 会耗费CPU资源 因此可以优化
注意支付服务可能已经支付 但是业务订单仍然显示未支付 还有就是回复库存可能是跨库操作 注意分布式事务的问题