java 延时消息和定时任务_Spring Cloud Stream 使用延迟消息实现定时任务(RabbitMQ)...

应用场景

通常在应用开发中我们会碰到定时任务的需求,比如未付款订单,超过一定时间后,系统自动取消订单并释放占有物品。

许多同学的第一反应就是通过spring的schedule定时任务轮询数据库来实现,这种方案有一下几点劣势:

(1)消耗系统内存,由于定时任务一直在系统中占着进程,比较消耗内存

(2)增加了数据库的压力,这个提现在两方面,一是长时间占着数据库的连接,而是查询基数大

(3)存在较大的时间误差

如果我们利用第三方插件如rabbitmq来实现,就可以解决以上几种问题。

对于任务的执行时间通常都是有规律性的,可能是每隔半小时执行一次,或者每天凌晨一点执行一次。然而实际业务中还存在另外一种定时任务,它可能需要一些触发条件才开始定时,比如:编写博文时候,设置2小时之后发送。对于这些开始时间不确定的定时任务,我们也可以通过Spring Cloud Stream来很好的处理。

为了实现开始时间不确定的定时任务触发,我们将引入延迟消息的使用。RabbitMQ中提供了关于延迟消息的插件,所以本文就来具体介绍以下如何利用Spring Cloud Stream以及RabbitMQ轻松的处理上述问题。

RabbitMQ延迟消息的插件安装

注意:只有RabbitMQ 3.6.x以上才支持

在下载好之后,解压得到.ez结尾的插件包,将其复制到RabbitMQ安装目录下的plugins文件夹。

8607daa3bc412b3e145e344571db43c2.png

然后cd到sbin目录下,启动插件

rabbitmq-plugins enable rabbitmq_delayed_message_exchange

8569460d8f41e183906f6b6e8f8562e6.png

启动成功,不需要重启rabbitmq

接下来,代码使用

config中心加入配置

# 消息队列配置

spring:

cloud:

# spring cloud strem 消息队列分组持久化(Input输入通道)

stream:

rabbit:

bindings:

commodityOrderInvalidInput:

consumer:

delayed-exchange: true

commodityOrderInvalidOutput:

producer:

delayed-exchange: true

bindings:

#延时的待付款订单

commodityOrderInvalidInput: #通道名

group: commodityOrderInvalidGroup #组名

destination: commodityOrderInvalidTheme #主题名

commodityOrderInvalidOutput:

destination: commodityOrderInvalidTheme #指定生产者的通道主题

注意这里的一个新参数spring.cloud.stream.rabbit.bindings.example-topic-output.producer.delayed-exchange,用来开启延迟消息的功能,这样在创建exchange的时候,会将其设置为具有延迟特性的exchange,也就是用到上面我们安装的延迟消息插件的功能。

在消费端也一样,需要设置spring.cloud.stream.rabbit.bindings.example-topic-output.producer.delayed-exchange=true

c849c861567254941ad244bd91c49f57.png

f0e5f5778d08b1bcbf0cbf2d600af1a7.png

0160e0ba62ef732b98f3501fcdfad8bd.png

消费端

9fd825a09fc656484a59ede14aeb3197.png

生产端

40b7c33bd5457e0529e45c82a2a6d87b.png

一条消息的头信息中包含了x-delay字段,该字段用来指定消息延迟的时间,单位为毫秒。所以上述代码发送的消息会在7秒之后被消费

1368ae6296e7221d4d26826854d2d35c.png

可以发现,该通道的type不一样

如果报以下错误

ERROR [o.s.a.rabbit.connection.CachingConnectionFactory] CachingConnectionFactory.java:1517 - Channel shutdown: channel error; protocol method: #method(reply-code=406, reply-text=PRECONDITION_FAILED - inequivalent arg 'type' for exchange 'commodityOrderInvalidTheme' in vhost '/': received ''x-delayed-message'' but current is 'topic', class-id=40, method-id=10)

那是之前没配置正确,通道创建的type类型是topic的

解决方式,检查配置是否正确,修改后,删除之前的通道或者修改通道的名称,重新启动创建通道,查看rabbitmq控制台,通道type类型为 x-delayed-message,说明成功了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是使用Spring Cloud Stream 4.0.3和RabbitMQ实现消息发送和接收的示例: 首先,需要在项目中添加Spring Cloud StreamRabbitMQ的依赖: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream-binder-rabbit</artifactId> <version>3.1.4</version> </dependency> ``` 接下来,在application.yml文件中配置RabbitMQ连接信息: ```yaml spring: rabbitmq: host: localhost port: 5672 username: guest password: guest ``` 定义消息发送和接收的接口: ```java public interface MessageChannels { String OUTPUT = "output"; @Output(OUTPUT) MessageChannel output(); } public interface MessageHandlers { String INPUT = "input"; @Input(INPUT) SubscribableChannel input(); } ``` 在需要发送消息的地方注入MessageChannels接口,并使用output()方法发送消息: ```java @Autowired private MessageChannels messageChannels; public void sendMessage(String message) { messageChannels.output().send(MessageBuilder.withPayload(message).build()); } ``` 在需要接收消息的地方注入MessageHandlers接口,并使用@StreamListener注解监听消息: ```java import org.springframework.cloud.stream.annotation.StreamListener; import org.springframework.stereotype.Component; @Component public class MessageReceiver { @StreamListener(MessageHandlers.INPUT) public void handleMessage(String message) { System.out.println("Received message: " + message); } } ``` 这样就完成了使用Spring Cloud StreamRabbitMQ实现消息发送和接收的示例。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值