RabbitMQ-进阶使用

https://rabbitmq.com/ttl.html

https://rabbitmq.com/dlx.html

https://rabbitmq.com/tutorials/tutorial-six-java.html

https://gitee.com/zhuqin2016/java-simple-demo/tree/master/rabbitmq-demo/src/main/java/org/zhuqin/simpledemo/rabbitmq

本文讲解 RabbitMQ 的两个进阶用法:

  • 延时队列
  • RPC

延时队列

延时队列实现依赖 RabbitMQ 的 TTL (time to live) 和 死信(Dead Letter)机制。

  • RabbitMQ 可以指定 Messages 和 Queues 的生存时间
  • Dead Letter,顾名思义,死亡的消息。死亡的消息会去到死信交易所-Dead Letter Exchange(DLX)。队列可以通过 dead-letter-exchange参数指定其产生的死信的 DLX。哪些消息会被认为是死信呢?
    • 被消费端拒绝接收 basic.reject的消息
    • 被消费端不签收basic.nack且不重新入队的消息
    • TTL 过期的消息
    • 因为队列长度限制导致丢弃的消息

了解了 TTL 和 Dead Letter 之后,我们可以按照下图的思路实现延时队列
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P3MGYwJv-1680188953595)(null#lake_card_v2=eyJ0eXBlIjoiZ3JhcGh2aXoiLCJjb2RlIjoiZGlncmFwaCBmaW5pdGVfc3RhdGVfbWFjaGluZSB7XG5cdHJhbmtkaXI9TFI7XG5cdHNpemU9XCI3LDNcIlxuICBub2RlIFtzaGFwZSA9IGNpcmNsZV07UHVibGlzaGVyO1xuICBQdWJsaXNoZXIgLT4gUUEgWyBsYWJlbCA9IFwiVFRMX01TR1wiXTtcbiAgUUEgLT4gRExYIFsgbGFiZWwgPSBcIkRlYWRfTGV0dGVyXCJdO1xuICBETFggLT4gUUIgWyBsYWJlbCA9IFwiTVNHX3dpdGhfUm91dGluZ0tleVwiXTtcbiAgUUIgLT4gQ29uc3VtZXIgWyBsYWJlbCA9IFwiTVNHXCJdO1xufSIsInVybCI6Imh0dHBzOi8vY2RuLm5sYXJrLmNvbS95dXF1ZS9fX2dyYXBodml6LzAzZWRjZWQwNjBkZmVjNjk5YWQ1Y2YzYzdhMzVjN2JkLnN2ZyIsImlkIjoicnF0Q1QiLCJtYXJnaW4iOnsidG9wIjp0cnVlLCJib3R0b20iOnRydWV9LCJjYXJkIjoiZGlhZ3JhbSJ9)]消息发布者先发送设置了 TTL 的消息给队列 QA,在消息过期后变成死信队列,自动转发到死信交易所 DLX,DLX 再把消息推送给与其绑定的队列 QB,QB再将消息分发给消费者。

发布者实现

  1. 声明死信交易所 DLX
  2. 声明队列 QB
  3. 绑定 DLX 和 QB,并指定 RoutingKey
  4. 生命队列 QA,指定 QA 的 DLX,指定 QA 的死信路由到 DLX 时使用的 RoutingKey
  5. 发送延时 10s 的消息
  6. 发送延时 1s 的消息

详细代码戳此

消费者实现

  1. 声明队列 QB
  2. 监听队列 QB 的消息

消息代码戳此

执行结果

  1. 启动发布者
  2. 启动消费者

消费者控制台:
image.png
可以看到延时 1s 的消息在延时 10s 的消息后收到,结果明显不符合延时队列的预期,这是因为 RabbitMQ 的队列默认是先进先出的(除了优先队列),10s 的消息到期出队后,1s 的消息再出队。
如何避免此问题:

  • 保证后发布的消息比先发布的消息存活的久
  • 声明多个接收 TTL 消息的队列,每个队列只接受 TTL 时间固定的消息

RPC(Remote Produce Call 远程调用)

消息队列也能实现 RPC 调用!

调用方 Client 发布消息(请求)到队列 rpc_queue,被调用方 Server 从rpc_queue接收消息(请求),Server 将请求响应结果发布到请求指定的队列 reply_to,Client 从 reply_to获取到请求结果

调用方实现

  1. 声明全局 Map 存放请求标识和响应实例(CompletableFuture)的映射
  • CompletableFuture.get 时会阻塞,等待其他线程调用 CompletableFuture.complete
  1. 声明回调队列,即接收响应结果的队列
  2. 异步监听回调队列的消息,收到消息根据消息携带的标识 correlationId找到对应的响应实例,调用 CompletableFuture.complete完成响应
  3. 生成消息携带的标识 correlationId
  4. 将响应实例放到全局 Map
  5. 将请求消息发布到被调用方声明的队列
  6. 调用CompletableFuture.get 等待完成响应

消息代码戳此

被调用方实现

  1. 声明接收请求消息的队列
  2. 监听请求消息
  3. 接受到请求,将响应结果发布到请求消息指定的回调队列

消息代码戳此

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值