数媒在线课堂 从 RocketMQ 看长轮询 (Long Polling)
消息队列一般在消费端都会提供 push 和 pull 两种模式,RocketMQ 同样实现了这两种模式,分别提供了两个实现类:DefaultMQPushConsumer 和 DefaultMQPullConsumer;两种方式各有优势:
️push 模式:推送模式,即服务端有数据之后立马推送消息给客户端,需要客户端和服务器建立长连接,实时性很高,对客户端来说也简单,接收处理消息即可;缺点就是服务端不知道客户端处理消息的能力,可能会导致数据积压,同时也增加了服务端的工作量,影响服务端的性能;
️pull 模式:拉取模式,即客户端主动去服务端拉取数据,主动权在客户端,拉取数据,然后处理数据,再拉取数据,一直循环下去,具体拉取数据的时间间隔不好设定,太短可能会导致大量的连接拉取不到数据,太长导致数据接收不及时;
RocketMQ 使用了长轮询的方式,兼顾了 push 和 pull 两种模式的优点,下面首先对长轮询做简单介绍,进而分析 RocketMQ 内置的长轮询模式。
长轮询
长轮询通过客户端和服务端的配合,达到主动权在客户端,同时也能保证数据的实时性;长轮询本质上也是轮询,只不过对普通的轮询做了优化处理,服务端在没有数据的时候并不是马上返回数据,会 hold 住请求,等待服务端有数据,或者一直没有数据超时处理,然后一直循环下去;下面看一下如何简单实现一个长轮询;
1. 实现步骤
1.1 客户端轮询发送请求
客户端应该存在一个一直循环的程序,不停的向服务端发送获取消息请求;
1.2 服务端处理数据
服务器接收到客户端请求之后,首先查看是否有数据,如果有数据则直接返回,如果没有则保持连接,等待获取数据,服务端获取数据之后,会通知之前的请求连接来获取数据,然后返回给客户端;
1.3 客户端接收数据
正常情况下,客户端会马上接收到服务端的数据,或者等待一段时间获取到数据;如果一直获取不到数据,会有超时处理;在获取数据或者超时处理之后会关闭连接,然后再次发起长轮询请求;
RocketMQ 长轮询
RocketMQ 的消费端提供了两种消费模式分别是:DefaultMQPushConsumer 和 DefaultMQPullConsumer,其中 DefaultMQPushConsumer 就是使用的长轮询
PullCallback 回调
服务端处理完之后,给客户端响应,回调其中的 PullCallback,其中在处理完消息之后,重要的一步就是再次把 pullRequest 放到 PullMessageService 服务中,等待下一次的轮询;