Spring Cloud Stream RabbitMQ 延迟消息实现

本文介绍了如何在RabbitMQ中通过设置消息过期时间和死信队列来模拟延迟队列。详细讲解了消息过期的两种设置方式,并提供了Spring Cloud Stream的配置方法,包括MessageChannel和SubscribableChannel的使用。最后讨论了延迟消息在订单超时失效等场景的应用。

在rabbitmq中不存在延时队列,但是我们可以通过设置消息的过期时间和死信队列来模拟出延时队列。消费者监听死信交换器绑定的队列,而不要监听消息发送的队列。

消息会进入死信队列的情况:

  1. 消息被拒绝(Basic.Reject或Basic.Nack)并且设置 requeue 参数的值为 false
  2. 消息过期了
  3. 队列达到最大的长度

我们使用第二种方式实现延时队列

如何设置过期时间:

在 rabbitmq 中存在2种方可设置消息的过期时间,第一种通过对队列进行设置,这种设置后,该队列中所有的消息都存在相同的过期时间,第二种通过对消息本身进行设置,那么每条消息的过期时间都不一样。如果同时使用这2种方法,那么以过期时间小的那个数值为准。当消息达到过期时间还没有被消费,那么那个消息就成为了一个 死信 消息。

    队列设置:在队列申明的时候使用 x-message-ttl 参数,单位为 毫秒

    单个消息设置:是设置消息属性的 expiration 参数的值,单位为 毫秒
 

配置

spring:
	cloud:
	    stream:
              #RabbitMQ服务器地址配置
	      binders:
	        windrabbit:
	          type: rabbit
	          environment:
	            spring:
	              rabbitmq:
	                addresses: localhost
	                port: 15672
	                username: guest
	                password: guest
              default:
                consumer:
                maxAttempts: 1 #默认为3次,禁用重试
	      bindings:
	        delay-output:
	          destination: delay.exchange #交换机
	          binder: windrabbit #指定mq配置
	          content-type: application/json
	          group: delay-order
	          producer:
	            requiredGroups: delay-order #没有消费者时声明这个才会创建队列
	        #delay-input:
	          #destination: delay.exchange
	          #binder: windrabbit
	          #content-type: application/json
	          #group: delay-order
	      #这一部分是给上边声明的bindings添加配置的,例如队列的ttl,还有要不要给队列配置死信队列
	      rabbit:
	        bindings:
	          delay-output:
	            producer:
	              ttl: 120000#队列里的消息如果120000ms之后还没被消费,就会成为死信,这个参数生效的前提是spring.cloud.stream.bindings里边声明了requiredGroups
	              autoBindDlq: true#这个参数为true的时候会自动为当前的队列创建一个死信队列,以dlq结尾

新建一个Processor来映射上边配置的bindings


public interface MQOrderProcessor {
//    不需要映射消息队列
//    String DELAYINPUT="delay-input";
//    @Input(MQOrderProcessor.DELAYINPUT)
//    SubscribableChannel delayOrderInput();

    String DELAYOUTPUT="delay-output";
    @Output(MQOrderProcessor.DELAYOUTPUT)
    MessageChannel delayOrderOutput();
}

@Output对MessageChannel,@Input对应SubscribableChannel,不少人用错,注意不要混用

(1)MessageChannel

MessageChannel 是Spring Integration消息通道的顶级接口:

在该接口中,没有提供从channel中接收消息的方法,这个是因为spring integration的channel有两个不同的机制来处理接收消息,polling 、subscription,分别有两个子接口来表示。

(2)PollableChannel

PollableChannel 具备轮询获得消息的能力,这种channel要求消息消费者或者框架去周期性的检查是否有可用的消息到达

(3)SubscribableChannel

SubscribableChannel 发送消息给订阅了MessageHanlder的订阅者

发送消息的代码

@AllArgsConstructor
@EnableBinding(MQOrderProcessor.class)
public class OrderMessageProvider  {

    private MQOrderProcessor processor;

    public boolean sendCancelOrderMessage(){
        System.out.println("start send message to mq");
        return processor.delayOrderOutput().send(MessageBuilder.withPayload("{message:'cancel order'}").build());
    }
}

接收死信队列消息

@RabbitListener(queues = "debug")
public void processMessage1(@Payload String body, @Header String token) {
    System.out.println("body:"+body);
    System.out.println("token:"+token);
}

这里也可以使用@StreamListener,自动转换对象和json

 

延迟消息使用场景

1. 订单超时失效。这种功能具有零散性,使用mq比使用定时任务更灵活、高效。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

xiegwei

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值