生产者
- 不建议单一进程创建大量生产者
Apache RocketMQ的生产者和主题是多对多的关系,支持同一个生产者向多个主题发送消息。对于生产者的创建和初始化,建议遵循够用即可、最大化复用原则,如果有需要发送消息到多个主题的场景,无需为每个主题都创建一个生产者。
- 不建议频繁创建和销毁生产者
Apache RocketMQ的生产者是可以重复利用的底层资源,类似数据库的连接池。因此不需要在每次发送消息时动态创建生产者,且在发送结束后销毁生产者。这样频繁的创建销毁会在服务端产生大量短连接请求,严重影响系统性能。
分组
RocketMQ 服务端 5.x 版本开始,生产者是匿名的,无需管理生产者分组(ProducerGroup);对于历史版本服务端 3.x 和 4.x 版本,已经使用的生产者分组可以废弃无需再设置,且不会对当前业务产生影响。
消费者
MQ的消费模式可以大致分为两种,一种是推Push,一种是拉Pull。
Push是服务端主动推送消息给客户端,Pull是客户端需要主动到服务端轮询获取数据。
他们各自有各自的优缺点,推优点是及时性较好,但如果客户端没有做好流控,一旦服务端推送大量消息到客户端时,就会导致客户端消息堆积甚至崩溃。
拉优点是客户端可以依据自己的消费能力进行消费,但是频繁拉取会给服务端造成压力,并且可能会导致消息消费不及时。
RocketMQ既提供了Push模式也提供了Pull模式,开发者可以自行选择。但是,我们需要注意的是,RocketMQ的push模式其实底层的实现还是基于通过创建一个轮询任务的pull实现的(每隔5秒拉一次),只不过他把pull给封装的比较好,让你以为是在push。
推的模式就消费者端和消息中间件建立TCP长链接或者注册一个回调,当服务端数据发生变化,立即通过这个已经建立好的长连接(或者注好的回调)将数据推送到客户端。
拉的模式就是消费者轮询,通过不断轮询的方式检查数据是否发生变化,变化的话就把数据拉回来。
如果使用拉的模式来实现消息队列的话,消费者可以完全自己掌控消息的数量及速度,这样可以大大的避免消息堆积的情况。但是,这种方案也有缺点,首先就是消费者需要不断的进行轮询,这种轮询也会对消息中间件造成一定的压力。
如果使用推的模式来实现,好处就是消息是实时的,一旦有消息过来消费者马上就能感知到。而且对于消费者来说也比较简单,不需要轮询,只需要等推送就行了。但是缺点也比较明显,那就是如果消息的生产速度大于消费速度,可能会导致消息大量堆积在消费者端,会对消费者造成很大的压力,甚至可能把消费者压垮。
一般来说,推的模式适合实时性要求比较高的场景。而拉的模式适合实时性要求没那么高的场景。
还有需要注意的就是,在有些生产环境下,服务器环境只能单向通信,也就是只能通过一端访问另外一端,而不能在反方向通信,此时就需要消费方使用拉模式,推模式是长链接,是双向通信,所以不行。
在很多中间件的实现上,可能并没有在直接用长连接或者轮询,而是把二者结合了一下,使用长轮询的方式进行拉消息的。
长轮询,就是消费者向消息中间件发起一个长轮询请求,消息中间件如果有消息就直接返回,如果没有也不会立即断开连接,而是等待一会,等待过程中如果有新消息到达,再把消息返回。如果超时还没有消息,那就结束了,等下次长轮询。比如Kafka和RocketMQ都是支持基于长轮询进行拉取消息的。
消息分发
RocketMQ支持两种消息分发模式:广播消费(Broadcasting)和集群消费(Clustering)。
- 集群模式(负载均衡模式,最常用):
特点:同一 Topic 下的一条消息只会被同一个消费者组中的一个消费者消费。也就是说,消息被负载均衡到了同一个消费组的多个消费者实例上。
优势:具有高可用性,即使其中一个消费者节点出现故障,其他节点仍然可以继续提供服务;可以实现负载均衡,消息在消费者组内的实例之间进行均衡分配,提高系统整体性能。
适用场景:适用于每条消息只需要被处理一次的场景,可通过扩缩消费者数量,来提升或降低消费能力。常用于大规模分布式系统,可以水平扩展。
- 广播模式:
特点:consumer 属于同一个 consumer group,消息会被 consumer group 中的每个 consumer 都消费一次,广播消费中 consumer group 概念可以认为在消息划分方面无意义。
优势:消息能够被所有消费者实例实时处理,适用于需要广播通知或实时更新的场景。
注意事项:不支持消息重试;每个消费者的消费进度是独立保存在客户端本地的;可能导致消息处理的并发度较高,需要确保消费者的处理逻辑能够支持高并发;要避免在广播模式下产生不必要的重复处理,例如数据库写入等。
适用场景:不需要负载均衡,每个消费者都需要处理所有消息的场景,如广告推送、实时通知等。
分组
消费者分组是多个消费行为一致的消费者的负载均衡分组。
消费者分组不是具体实体而是一个逻辑资源。通过消费者分组实现消费性能的水平扩展以及高可用容灾。
消费者分组中的订阅关系、投递顺序性、消费重试策略是一致的。
- 订阅关系:Apache RocketMQ 以消费者分组的粒度管理订阅关系,实现订阅关系的管理和追溯。
- 投递顺序性:Apache RocketMQ 的服务端将消息投递给消费者消费时,支持顺序投递和并发投递,投递方式在消费者分组中统一配置。
- 消费重试策略: 消费者消费消息失败时的重试策略,包括重试次数、死信队列设置等。
RocketMQ 服务端 5.x 版本:上述消费者的消费行为从关联的消费者分组中统一获取,因此,同一分组内所有消费者的消费行为必然是一致的,客户端无需关注。