消息拉取长轮询,rocketMq是怎么玩的

在服务端客户端架构中,如果客户端对服务端的某些信息变动事件感兴趣,当服务端的这些信息变动后,客户端如何即时获取到这些信息?简单来说,服务器端如何即时地将数据的更新或变化反应到客户端?这是我们今天要讨论的问题

其实说白了,服务端有信息变化,要嘛服务端推送给客户端,要嘛客户端自己去拉,没有其他选择,服务端推的叫push模式,客户端拉的叫pull模式。二者的区别就在于谁主动,谁被动

push模式主动权在服务端,指的是服务端维持与客户端的长连接通道,一旦有更新,通过长连接通道推送给客户端,优点就是及时,一旦有数据变更,客户端可以很快获取到,缺点也很明显,客户端是被动的,服务端不知道客户端的数据处理能力,可能导致数据积压在客户端,来不及处理;

pull模式主动权在客户端,指的是客户端向服务端发出请求拉取数据,pull模式又分为普通轮询长轮询两种方式

      普通轮询比较简单,就是定时发起请求,服务端收到请求后不论数据有没有更新都立即回复,优点就是实现简单,容易理解,缺点就是服务端是被动的,服务端要不断的处理客户端连接,并且服务端无法控制客户端pull的频率以及客户端数量,所以服务端承受的压力是未知的,除非可以明确评估服务端可能承受的pull压力,否则不推荐这种方式;

       长轮询是对普通轮询的优化,依然由客户端发起请求,服务端收到后并不立即响应,而是hold住客户端连接,等待数据产生变更后(或者超过指定时间还未产生变更)才回复客户端,说白了,就是对普通轮询加了个控制,你客户端可以随时请求我,但是回不回复我说了算,这就保证了服务端不会被客户端带节奏,导致自己的压力不可控

好了,下面就让我们看看rocketMq中,消息是如何到达客户端的:

       rocketMq对pull和push方式的消息获取都有支持,push不是本文的重点,我们就重点看看pull模式在rocketMq中是怎样实现的。首先要表明的是,在pull消息时,rocketMq也是使用了长轮询方式

       消费者主动发起pull请求,broker在处理消息拉取请求时,如果没有查询到消息,将不返回消费者任何信息(相当于挂起消费者,使其不会立即发起下一次拉取请求),会将请求信息pullRequest添加到pullRequestTable中,等待触发通知消费者的事件(pullRequestTable表示待处理的消息拉取请求,其中包含了消费者信息(可以据此获取与该消费者的长连接channel),以及其想要拉取的消息位置,后面需要根据这些信息来将对应的新消息返回给对应的消费者)

       broker中,有两个地方会触发该事件:

       1).DefaultMessageStore.ReputMessageService.run(定时任务,1毫秒一次)

不断的检测是否有新消息产生,如果检测到了,就发出消息到达通知,将新消息发送给对应的消费者

       2).PullRequestHoldService.run(定时任务,5s一次),该任务会逐个检查pullRequestTable中的pullRequest,判断是否有对应的新消息产生。如果有则返回给消费者;没有则检查该pullRequest从加入到现在是否已经超过长轮询等待时间(默认15秒),如果是,也会返回消费者

消费者收到broker返回后,无论是否有收到新消息,都会在处理完成后发起下一次的pull请求

PS:如果有不足之处,欢迎指出;如果解决了你的疑惑,就点个赞吧o(* ̄︶ ̄*)o

猜你喜欢

转载自blog.csdn.net/wb_snail/article/details/89278231