生产端消息可靠性保证: 确认(Confirm)机制

本文介绍了JavaEE中的@PostConstruct注解的使用以及RabbitMQ中的PublisherConfirms(确认消息到达交换机)和PublisherReturns(消息路由失败退回)机制,包括配置和代码实现示例,展示了如何在Spring框架中管理Bean的初始化和消息确认流程。
摘要由CSDN通过智能技术生成

1.@PostConstruct注解

@PostConstruct注解是Java EE规范中的一部分,主要用于标记在一个Bean初始化完成后需要执行的方法。这个注解由JSR-250定义,并且在Spring框架以及其他遵循Java EE标准的应用服务器中广泛支持。

功能与用途:初始化方法,当容器完成对Bean的实例化并且所有依赖注入完成后,将会自动调用标有@PostConstruct注解的方法。这为开发者提供了一个机会,在对象正式投入使用之前进行一些必要的初始化工作,比如初始化资源、预计算某些值、启动后台任务等增强。

2. Publisher Confirms(发布者确认)

作用: Publisher Confirm机制允许RabbitMQ服务器通知生产者一个消息是否已经被交换机正确接收。当publisher-confirm-type设置为CORRELATED时,RabbitMQ会向生产者发送确认或否定响应,确认消息已到达交换机,但不保证消息已被路由到至少一个队列中。

生产者到交换机的确认(消息到达交换机)

2.1.配置:

spring.rabbitmq.publisher-confirm-type = CORRELATED

2.2. 代码实现

只要到达交换机就会触发

rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (ack) {
            // 消息成功投递成功并被确认
        } else {
            // 消息未能正确投递
        }
    }
});

3.Publisher Returns(发布者退回)

作用: Publisher Return机制用于当消息无法按照路由键规则路由到任何队列时,或者由于其他原因(例如队列满、消息过大等)而被交换机拒绝时,RabbitMQ将消息返回给生产者。

交换机到队列的确认(消息是否正常发送到了队列)

通过实现 ReturnCallback 接口,发送消息失败返回,比如交换机路由不到队列时触发回调:

1.只有消息没有路由到队列的时候,才触发该回调 .

2.只要有一个队列接受到消息了,它就认为成功.

3.1 配置

spring.rabbitmq.publisher-returns = true

3.2 代码实现

rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        // 处理未被路由或因某种原因被退回的消息
    }
});

4.完整代码



@Slf4j
@Service
public class DirectProvider implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    //注解是专门数据初始化的注解, 只有其他组件注入后,初始化方法才会执行,
    @PostConstruct
    public void init() {
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnCallback(this);
    }

    public  void  send(OrderingOk orderingOk){

        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        System.out.println("callbackSender UUID: " + correlationData.getId());
        rabbitTemplate.convertAndSend(
                "Direct_E01", 
                "test",orderingOk,
                m-> m,correlationData);
    }

    /**
     * 确认消息是否被交换机接收。
     *
     * @param correlationData 包含消息相关数据的对象,用于识别消息的唯一性。
     * @param ack 表示消息是否被交换机确认接收。
     * @param cause 如果消息未被接收,提供未接收的原因。
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        // 获取相关数据的ID,如果相关数据为空,则设置为空字符串
        String id = correlationData != null ? correlationData.getId() : "";
        // 如果消息被确认接收,则记录日志
        if (ack) {
            log.info("交换机已经收到了ID为:{}的消息", id);
        } else {
            // 如果消息未被确认接收,则记录包括未接收原因的日志
            log.info("交换机还未收到ID为:{}的消息,由于原因:{}", id, cause);
        }

    }

    /**
     * 记录被交换机退回的消息信息。
     *
     * @param message 消息对象,包含消息体。
     * @param replyCode 返回的响应代码,用于指示退回的原因。
     * @param replyText 返回的响应文本,提供关于退回的详细信息。
     * @param exchange 退回时涉及的交换机名称。
     * @param routingKey 退回时使用的路由键。
     */
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        // 记录消息退回的日志信息
        log.info("消息{},被交换机:{}退回,原因是:{},路由key是:{}", new String(message.getBody()), exchange, replyCode, replyText, routingKey);
    }

RabbitMQ通过以下几种机制保证消费消息可靠性: 1. 确认机制(Ack机制):消费在成功消费一条消息后,会向Broker发送Ack确认报文,告知自己已完成消费。如果Broker没有收到确认报文,那么消息不会被标记为已消费,从而避免了消息的丢失。然而,如果消费者在发送确认报文时由于网络断开等原因无法成功发送,会导致消息重复消费的问题。 2. 发布者确认Publisher Confirm):生产者在发送消息后可以等待RabbitMQ返回确认通知。如果生产者接收到确认通知,就可以判断消息已被成功发送到Broker。如果网络断开或其他异常情况导致确认通知无法及时返回,生产者可以选择重新发送消息,以确保消息可靠性。然而,这可能会导致RabbitMQ中存在两条相同的消息,从而可能导致重复消费的问题。 3. QoS机制(Quality of Service):RabbitMQ提供了QoS保证机制,可以限制消费在一个Channel上未被Ack的消息数量。如果超过了这个数量限制,RabbitMQ将不再向消费推送消息,以避免消费因大量消息瞬时到达而产生巨大压力。这是一种流控手段,能够保护消费可靠性。但需要注意的是,QoS机制仅对消费的推模式有效,对拉模式无效;同时,QoS机制不支持NONE Ack模式。 综上所述,RabbitMQ通过Ack机制、发布者确认和QoS机制保证消费消息可靠性。然而,由于网络断开和其他异常情况的存在,无法完全避免消息的重复消费。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值