消息队列,推拉模式的区别在哪?

大家好,我是【架构摆渡人】,一只十年的程序猿。这是消息队列的第五篇文章,这个系列会给大家分享很多在实际工作中有用的经验,如果有收获,还请分享给更多的朋友。

在学习消息队列的时候,大家都有一个共同的问题,那就是消息到底是服务端推送给客户端还是客户端主动去服务端拉取然后进行消费。今天这篇文章就来解答大家的这个的疑问。

推模式

首先我们来解决下什么是推模式,顾名思义,推模式就是我推给你。在MQ中也就是Broker收到消息后主动推送给Consumer的操作,叫做推模式。

推模式的实现是客户端会与服务端(Broker)建立长连接,当有消息时服务端会通过长连接通道将消息推送给客户端,这样客户端就能实时消费到最新的消息。

优点:

  • 实时性强,有消息立马推送给客户端。

  • 客户端实现简单,只需要监听服务端的推送即可。
    缺点:

  • 容易导致客户端发生消息堆积的情况,因为每个客户端的消费能力是不同的,如果简单粗暴的有消息就推送,就会会出现堆积情况。

  • 服务端逻辑复杂,因为简单的推送会导致客户端出现堆积问题,所以服务端需要进行优化。记录给每个客户端的推送数据,然后根据每个客户端的消费能力去平衡数据推送的速度。

拉模式

拉模式,顾名思义,就是我主动去拉取消息。在MQ中也就是Consumer主动向Broker询问:有没有消息啊,有的话给我一部分呗,我先拉1000条进行处理,处理完成之后再拉1000条。

拉模式肯定不能用传统的定时拉取,定时长及时性无法保证,定时短,在没有消息的情况下对服务端会一直请求。所以很多拉模式都是基于长轮询来实现。

长轮询就是客户端向服务端发起请求,如果此时有数据就直接返回,如果没有数据就保持连接,等到有数据时就直接返回。如果一直没有数据,超时后客户端再次发起请求,保持连接,这就是长轮询的实现原理。很多的开源框架都是用的这种方式,比如配置中心Apollo的推送。

优点:

  • 不会造成客户端消息积压,消费完了再去拉取,主动权在自己手中。

  • 长轮询实现的拉模式实时性也能够保证。
    缺点:

  • 客户端的逻辑实现相对复杂点,简化了服务端的逻辑。
    推和拉都有各自的优势和劣势,不过目前主流的消息队列大部分都用的拉模式,比如RocketMQ,Kafka。

拉模式代码实现

Java中可以使用Spring DeferredResult来实现异步请求,如果有消息就直接返回,没有消息则将此请求存储起来,等到有消息是再通知该请求进行返回。如果一直没有消息那么就等到超时,客户端收到超时消息重新进行消息的查询。

首先我们定义一个消息查询的接口,定义如下:

@GetMapping("/queryMessage")
public DeferredResult<String> queryMessage(String client) {
   
    DeferredResult<String> deferredResult = new DeferredResult<>(10000L);
    String msg = messageQueue.poll();
    if (Objects.nonNull(msg)) {
   
        deferredResult.
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值