SpringCloudStream——RabbitMQ 手动ACK,Channel 参数为空?

9 篇文章 1 订阅

问题描述

使用SpringCloudStream 集成RabbitMQ的过程中,一直无法使用手动ACK功能。
在这里插入图片描述
SpringCloud版本:Hoxton.RELEASE
SpringBoot 版本:2.2.1.RELEASE
SpringCloudStream 版本 :3.0.0.RELEASE
MQ 配置文件:

spring:
  cloud:
    stream:
      bindings:
        greetings-in:
          destination: greetings
          contentType: application/json
        greetings-out:
          destination: greetings
          contentType: application/json
      binders:
        defaultRabbit:
          type: rabbit
          environment:
            spring:
              rabbitmq:
                host: localhost
                port: 5672
                username: guest
                password: guest

原因分析:

配置问题,导致无法绑定对应的channel

在这里插入图片描述

解决方案:

配置文件:

spring:
  cloud:
    stream:
      rabbit:
        bindings:
          greetings-in:
            consumer:
              acknowledge-mode: manual
      bindings:
        greetings-in:
          destination: greetings
          contentType: application/json
          consumer:
            acknowledge-mode: manual # manual手动确认 ,auto 自动确认
        greetings-out:
          destination: greetings
          contentType: application/json
      binders:
        defaultRabbit:
          type: rabbit
          environment:
            spring:
              rabbitmq:
                host: localhost
                port: 5672
                username: guest
                password: guest

消费者:

@Slf4j
@EnableBinding(GreetingsStreams.class)
public class GreetingsListener {
    @StreamListener(GreetingsStreams.INPUT)
    public void handleGreetings(Message<Greetings> entityMessage) {
        Channel channel = entityMessage.getHeaders().get(AmqpHeaders.CHANNEL, Channel.class);
        Long deliveryTag = entityMessage.getHeaders().get(AmqpHeaders.DELIVERY_TAG, Long.class);
        try {
            log.info("Received message: {} ,channel :{} , deliveryTag: {} ", entityMessage.getPayload(), channel, deliveryTag);
            Thread.sleep(10000);
            Random rand = new Random();
            int i = rand.nextInt(10);
            log.info("产生的随机数是:{}", i);
            if (i > 5) {
                /**消息确认**/
                channel.basicAck(deliveryTag, false);
            } else {
                /**重回队列**/
                channel.basicReject(deliveryTag, true);
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }
}

basicReject / basicNack / basicRecover区别

channel.basicReject(deliveryTag, true);
basic.reject方法拒绝deliveryTag对应的消息,第二个参数是否requeue,true则重新入队列,否则丢弃或者进入死信队列。
该方法reject后,该消费者还是会消费到该条被reject的消息。

channel.basicNack(deliveryTag, false, true);
basic.nack方法为不确认deliveryTag对应的消息,第二个参数是否应用于多消息,第三个参数是否requeue
,与basic.reject区别就是同时支持多个消息,可以nack该消费者先前接收未ack的所有消息。nack后的消息也会被自己消费到。

channel.basicRecover(true);
basic.recover是否恢复消息到队列,参数是是否requeue,true则重新入队列,
并且尽可能的将之前recover的消息投递给其他消费者消费,而不是自己再次消费。false则消息会重新被投递给自己。

在这里插入图片描述

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值