【番外】Springboot集成推荐配置及十问RocketMQ


如果要解答rocketMQ的相关问题,一定要区分rocketMq的版本,4.X和5.0实现差异比较大,很多实现原理是使用方式都有很大的变化。以下解答仅使用于4.7.1版本。

Springboot推荐配置方式

RocketMq集成到Springboot项目中官方提供的starter包非常的简单高效,但很多项目其实还是用着Spring的方式去集成,虽然效果差不多,但如果每个项目都使用老的配置方式,累计花的时间及重复的轮子也是需要考虑的。Springboot集成的推荐配置方式如下文:

Springboot推荐配置方式

十问

1. 为什么springboot系统集成只有一个producer,并集成到RocketMQTemplate里面?

springboot集成rocketMq时,仅提供实例化单个生产组的producer和对应的RocketMQTemplate,相当于官方鼓励一个系统仅使用一个生产组的producer;而consumer则是通过注解@RocketMQMessageListener来实现实例化,且实例化的类型为DefaultMQPushConsumer,如果要实现PullConsumer则需要开发者自定义实现。RocketMQ的生产者和topic是多对多的关系,支持同一个生产者向多个topic发送消息,对于生产者遵循够用即可,最大复用原则,因此只需要创建一个生产者,无需为每个主题都创建一个生产者,不建议频繁的创建和销毁生产者。而RocketMQTemplate顾名思义是官方包装了一层方法提供给开发者使用。

2. 为什么consumer必须要再额外使用一个MessageListener来处理消息?

通过@RocketMQMessageListener注册的消费者都是PushConsumer,而PushConsumer内部封装了ConsumeMessageService对象,实现类分别是随机消费ConsumeMessageConcurrentlyService和顺序消费ConsumeMessageOrderlyService,因此外部的DefaultMQPushConsumer只是封装了基础信息的封装类,真实的消费拉取消息逻辑在其他的类里面。而@RocketMQMessageListener注解则是提供消费者订阅topic所需的各种信息。

3. 一个系统只用一个producer和consumer可不可行?对比多个producer/consumer使用起来有什么差异?

一个系统只用一个producer是没问题的,并且这是官方建议的用法。而consumer则不一样,一个consumer只推荐消费同一个topic+tag组,因此如果一个系统要承担消费多个topic+tag组的职责,则需要创建多个consumer。

4. Pull和Push的consumer差异?

Push其本质也是Pull,只是官方做了一些封装,使用Reactor线程模型去Broker拉取消息缓存到本地,再交给MessageListener做随机或顺序消费。而Pull则是最原始的方式,拉取消息、提交消息等操作都需要开发者自行实现,适用于特殊业务制定的场景。

5. TransactionProducer和DefaultProducer的差异和关系?

TransactionProducer是DefaultProducer的子类,而TransactionListener则是TransactionProducer开放出来监听查询程序事务回调的接口,发送事务消息的方法也是继承自DefaultProducer,只是DefaultProducer的事务方法直接调用会抛异常,事务消息发送完将是UNKNOW状态,等带监听器的COMMIT/ROLLBACK。

6. 消费群组要保持统一的消费行为和策略具体指的是什么?能否一个组里使用事务消息、另一个使用顺序消息等?

消费群组要保持统一的消费行为指的是同一个消费组下面的消费者,其订阅的topic、tag要一样,且ConsumeMode和MessageModel都要保持一致,否则容易导致统一消费组的消费者消费的消息不一致或消息丢失。事务消息类型对消费者是不可知的,仅发生在生产者和Broker之间。顺序消息和并发消息才是对应的,如果两者真的同时存在,根据其实现原理推测,两个消费者都可以按照其配置进行消息,只是会存在消息消费处理不一致的情况,容易导致业务异常。

7. 官方不建议同一个组内订阅同一个topic的不同tag?

先说一个大前提:producer真的生产了这些tag的消息,且这些消息被分配到了topic下的各个队列中。如果tag不一致,如C1订阅了全的tag,而C2只订阅了其中一个,因为消息队列在同一个消费组中只会被一个consumer消费,那么C1可以消费分配到队列的所有消息,而C2却只能消费分配到队列的其中一个tag消息,被C2订阅的消息队列其它tag消息都会丢失!因此同一个消费组的topic+tag组需要一致,而不同消费组因为是重新分配消息队列了,因此又是一组新的topic+tag组关系。

8. 什么情况下MQ会丢失消息?

需要从两个方面入手:一、Master Broker宕机导致刷盘同步失败丢失,几率极小,一旦发生必丢失消息,且新的消息也无法发送,如果无法保证MQ集群的稳定性,业务则需要有降级的容错处理,如手动记录,并使用定时任务补偿,或牺牲吞吐量设置同步刷盘(不建议)。二、业务配置或消费不合理导致丢失,如topic+tag组配置不合理,消费者继续使用异步处理消息且没有处理异常情况的程序bug等也会导致消费了但消息丢失的情况。

9. 顺序消息是如何实现的?如果更改了队列数量会有什么影响?

如果通过RocketMqTemplate发送顺序消息,其使用的取模方法是取hash值再对队列数量取模,用这个来确定消息存放在哪个队列中。队列数量发生变化后,无论取模逻辑是什么,很难避免切换时消息发生乱序,唯一能做的便是在消费端做好消费乱序的降级处理,保证就算乱序消费对业务产生的影响也比较小。

10. 广播消费模式时如果某个服务是双机是否会对同一个消息处理两次?

广播模式下同一个消费组的所有消费者都会消费这条消息,和几机没有关系。如果存在双机系统,只需要其中的一台消费某条消息,就不应该设置成广播模式,而应该是集群模式,这样整个消费组集群则只会消费一次。如果另一个业务场景需要消费也只需要新创建一个消费组集群再去消费一次即可。

相关推荐

  1. Springboot集成推荐配置RocketMQ

    2024-07-12 10:40:04       28 阅读
  2. Springboot 集成 RocketMq5+ (gRPC 协议)

    2024-07-12 10:40:04       79 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-12 10:40:04       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-12 10:40:04       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-12 10:40:04       58 阅读
  4. Python语言-面向对象

    2024-07-12 10:40:04       69 阅读

热门阅读

  1. 软设之职责链模式

    2024-07-12 10:40:04       20 阅读
  2. vue中ref()与reactive(的区别)

    2024-07-12 10:40:04       20 阅读
  3. Flask发布一个及时止损(止盈)服务(二)

    2024-07-12 10:40:04       21 阅读
  4. NoSQL之Redis数据库配置与优化

    2024-07-12 10:40:04       27 阅读
  5. ELK优化

    2024-07-12 10:40:04       29 阅读
  6. AI正在取代程序猿?

    2024-07-12 10:40:04       24 阅读