rabbitMq可靠性投递之配置(消息至交换机,至队列不通的回调) -- 转载

rabbitMq可靠性投递之配置(消息至交换机,至队列不通的回调)

记录mq学习的一个bug,配置了mandatory为true,可是callback却不生效。网上搜了一圈,发现该篇文章, 在此记录下:
转载连接:https://www.cnblogs.com/wangbiaohistory/p/14630493.html

   @Bean
    public RabbitTemplate rabbitTemplate(CachingConnectionFactory factory) {
//若使用confirm-callback ,必须要配置publisherConfirms 为true
        factory.setPublisherReturns(true);
        //若使用return-callback,必须要配置publisherReturns为true
        factory.setPublisherReturns(true);
        RabbitTemplate rabbitTemplate = new RabbitTemplate(factory);
        //使用return-callback时必须设置mandatory为true,或者在配置中设置mandatory-expression的值为true
        rabbitTemplate.setMandatory(true);
 
        // 如果消息没有到exchange,则confirm回调,ack=false; 如果消息到达exchange,则confirm回调,ack=true
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                if(ack){
                    System.out.println("消息发送成功:correlationData({}),ack({}),cause({})"+correlationData+":"+ack+":"+cause);
                }else{
                    System.out.println("消息发送成功:correlationData({}),ack({}),cause({})"+correlationData+":"+ack+":"+cause);
                }
            }
        });
 
        //如果exchange到queue成功,则不回调return;如果exchange到queue失败,则回调return(需设置mandatory=true,否则不回回调,消息就丢了)
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            @Override
            public void returnedMessage(ReturnedMessage returnedMessage) {
                System.out.println("消息丢失:exchange({}),route({}),replyCode({}),replyText({}),message:{}"+JSON.toJSONString(returnedMessage));
            }
        });
        return rabbitTemplate;
    }

解决办法:若使用confirm-callback,factory必须要配置publisherConfirms 为true, 若使用return-callback,必须要配置publisherReturns为true

### RabbitMQ 消息未送达交换机的原因分析 在 RabbitMQ消息传递模型中,生产者发送的消息会先经过交换机 (Exchange),然后再通过绑定关系分发到对应的队列。然而,在某些情况下,可能会发生消息未能成功投递交换机的情况。 #### 可能原因及解决方案 1. **交换机不存在** - 如果指定的交换机名称错误或尚未创建,则消息无法找到目标交换机并会被丢弃。 - 解决方案:确认交换机已存在,并确保其名称拼写正确。可以通过管理界面或 API 创建所需的交换机[^4]。 2. **路由键配置错误** - 生产者发送消息时使用的路由键可能不符合交换机的要求。不同的交换机类型(Direct、Topic、Fanout、Headers)对路由键有不同的解析逻辑。 - 解决方案:检查路由键是否与所选交换机类型的规则相匹配。例如,对于 Direct 类型的交换机,路由键必须精确匹配;而对于 Topic 类型的交换机,支持通配符模式匹配。 3. **网络连接异常** - 若生产者的网络连接不稳定或中断,可能导致消息丢失。 - 解决方案:启用 Publisher Confirms 功能来验证消息是否成功抵达交换机。如果启用了 `mandatory` 参数而消息仍未到达预期队列,则触发 Return Callback 机制通知生产者进行重试或其他操作[^2]。 4. **权限不足** - 当前用户缺乏向特定虚拟主机下的资源发布数据的权利也可能阻碍正常流程。 - 解决方法:授予该账户足够的访问权限以便它可以执行所需的操作。 5. **策略限制** - 集群内部可能存在一些高级别的流量控制或者安全设定影响着外部输入的数据流走向。 - 应对措施:审查相关文档资料以及联系管理员调整相应参数直至满足业务需求为止。 ### 实现可靠性的建议代码片段 为了提高系统的健壮性和可靠性,下面提供了一个基于 Spring AMQP 的实现例子: ```java // 设置返回回调函数用于捕获未路由成功的消息 rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> { System.err.println("Message returned with code:" + replyCode); System.err.println("Reason given was '" + replyText + "'"); // 尝试重新发送失败的信息至备用队列或者其他处理手段... }); // 发送带有强制标志的消息以激活上述回调功能 rabbitTemplate.convertAndSend("my.exchange", "wrong.routing.key", myMessageObject, new CorrelationData(UUID.randomUUID().toString()), MessagePostProcessor mpp -> { ((org.springframework.amqp.core.Message)mpp.postProcessBeforeSend()).getMessageProperties() .setMandatory(true); return null; }); ``` 以上示例展示了如何利用 Return-Callback 来监控那些由于找不到合适的目标队列而导致退回给源头端的消息实例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值