本文主要讲解RabbitMQ的部分应用场景以及具体代码的实现
1.应用场景
目前常见的应用软件都有消息的延迟推送的影子,应用也极为广泛,例如:
- 淘宝七天自动确认收货。在我们签收商品后,物流系统会在七天后延时发送一个消息给支付系统,通知支付系统将款打给商家,这个过程持续七天,就是使用了消息中间件的延迟推送功能。
- 12306 购票支付确认页面。我们在选好票点击确定跳转的页面中往往都会有倒计时,代表着 30 分钟内订单不确认的话将会自动取消订单。其实在下订单那一刻开始购票业务系统就会发送一个延时消息给订单系统,延时30分钟,告诉订单系统订单未完成,如果我们在30分钟内完成了订单,则可以通过逻辑代码判断来忽略掉收到的消息。
在上面两种场景中,如果我们使用下面两种传统解决方案无疑大大降低了系统的整体性能和吞吐量:
- 使用 redis 给订单设置过期时间,最后通过判断 redis 中是否还有该订单来决定订单是否已经完成。这种解决方案相较于消息的延迟推送性能较低,因为我们知道 redis 都是存储于内存中,我们遇到恶意下单或者刷单的将会给内存带来巨大压力。
- 使用传统的数据库轮询来判断数据库表中订单的状态,这无疑增加了IO次数,性能极低。
- 使用 jvm 原生的 DelayQueue ,也是大量占用内存,而且没有持久化策略,系统宕机或者重启都会丢失订单信息。
2.消息延迟推送的实现
在 RabbitMQ 3.6.x 开始,RabbitMQ 官方提供了延迟队列的插件,可以下载放置到 RabbitMQ 根目录下的 plugins 下:延迟队列插件下载
然后开启rabbitmq_delayed_message_exchange插件
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
通过命令:
rabbitmq-plugins list
可以查看插件的列表:
3.生产端
目录结构
application.yml 配置
spring:
rabbitmq:
port: 5672
host: localhost
username: guest
password: guest
virtual-host: /
connection-timeout: 15000
#开启 confirm 确认机制
publisher-confirms: true
#开启 return 确认机制
publisher-returns: true
template:
mandatory: true
server:
port: 8080
4.消费端
在实际生产环境中,生产端和消费端一般都是两个系统,我们在此也将拆分成两个项目。
目录结构
application.yml 配置
spring:
rabbitmq:
port: 5672
host: localhost
username: guest
password: guest
virtual-host: /
#设置消费端手动 ack
listener:
simple:
acknowledge-mode: manual
#消费者最小数量
concurrency: 1
#消费之最大数量
max-concurrency: 10
#在单个请求中处理的消息个数,他应该大于等于事务数量(unack的最大数量)
prefetch: 2
server:
port: 8081
5.运行效果
5.1运行消费端
5.2运行生产端
5.3查看消费端
由于我延时时间设置的为6秒钟,所以6秒后消费端收到消息。
6.获取代码
关注公众号:理木客 ,后台回复:mq111 ,即可获取两个项目的完整代码。