RabbitMQ问题系列:(一)

1 监听方法不能有返回值

  • 警告信息:
    org.springframework.amqp.rabbit.support.ListenerExecutionFailedException: Listener threw exception
    Caused by: org.springframework.amqp.rabbit.listener.adapter.ReplyFailureException: Failed to send reply with payload ‘InvocationResult [returnValue=“stringfadfadfa”, returnType=class java.lang.String, bean=com.company.microservicedata.service.impl.MessageQueueReceiveServiceImpl@34abfdbf, method=public java.lang.String com.company.microservicedata.service.impl.MessageQueueReceiveServiceImpl.topicManyReceive(org.springframework.amqp.core.Message,com.rabbitmq.client.Channel) throws java.io.IOException]’
    Caused by: org.springframework.amqp.AmqpException: Cannot determine ReplyTo message property value: Request message does not contain reply-to property, and no default response Exchange was set.
  • 原因
    消费方法(监听消息并接收消息的方法)使用了返回值。
    源码:org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener#doHandleResult中调用的org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener#getReplyToAddress方法抛出的异常,其中responseAddress为null,触发AmqpException。

org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener#doHandleResult

在这里插入图片描述

org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener#getReplyToAddress
在这里插入图片描述

  • 方案
    监听方法无返回值,void,样例如下:
@Override
@RabbitListener(queues="queue_n")
public void topicManyReceive(Message msg, Channel channel) throws IOException {
    try {
        logger.info("接收成功--Topic交换机queue_n: {}", msg);
        channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
    } catch(Exception e) {
        channel.basicNack(msg.getMessageProperties().getDeliveryTag(), false, true);
        logger.info("接收失败: {}", e);
    }
}

2 不能多次ACK

  • 错误信息
    Channel shutdown: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - unknown delivery tag 1, class-id=60, method-id=80)
    Channel shutdown: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - unknown delivery tag 1, class-id=60, method-id=80)
  • 原因
    多次调用ACK,即配置了自动ACK之后,又手动调用了basicAck方法,两次确认消息
  • 方案
    一次确认消息,即,配置了自动确认,禁止手动调用basicAck方法,配置手动确认,则需要主动调用确认方法basicAck方法
    (1)自动确认
    配置文件:
rabbitmq:
    host: 192.168.1.5
    port: 5672
    username: xindaqi
    password: 123456
    publisher-returns: true
    listener:
      direct:
        acknowledge-mode: auto
      simple: 
        acknowledge-mode: auto
        concurrency: 1 # 当前监听容器数
        max-concurrency: 1 # 最大监听数
        #retry:
        #  enabled: true # 支持重试
@Override
@RabbitListener(queues="queue_n")
public void topicManyReceive(Message msg, Channel channel) throws IOException {
    try {
        logger.info("接收成功--Topic交换机queue_n: {}", msg);
    } catch(Exception e) {
        logger.info("接收失败: {}", e);
    }
}

(2)手动确认
配置信息:

rabbitmq:
    host: 192.168.1.5
    port: 5672
    username: xindaqi
    password: 123456
    publisher-returns: true
    listener:
      direct:
        acknowledge-mode: manual
      simple: 
        acknowledge-mode: manual
        concurrency: 1 # 当前监听容器数
        max-concurrency: 1 # 最大监听数
        #retry:
        #  enabled: true # 支持重试

监听消息:

@Override
@RabbitListener(queues="queue_n")
public void topicManyReceive(Message msg, Channel channel) throws IOException {
    try {
        logger.info("接收成功--Topic交换机queue_n: {}", msg);
        channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
    } catch(Exception e) {
        channel.basicNack(msg.getMessageProperties().getDeliveryTag(), false, true);
        logger.info("接收失败: {}", e);
    }
}

【参考文献】
[1]https://blog.csdn.net/qq_15071263/article/details/99976534
[2]https://blog.csdn.net/chenzt8812/article/details/100630565/
[3]https://blog.csdn.net/wxb880114/article/details/105854584

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天然玩家

坚持才能做到极致

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值