首页 > 代码库 > RocketMQ3.2.2生产者发送消息自动创建Topic队列数无法超过4个

RocketMQ3.2.2生产者发送消息自动创建Topic队列数无法超过4个

问题现象

RocketMQ3.2.2版本,测试时尝试发送消息时自动创建Topic,设置了队列数量为8

producer.setDefaultTopicQueueNums(8);

同时设置broker服务器的配置文件broker.properties

defaultTopicQueueNums=16

 

但实际创建后从控制台及后台打印代码观察到该Topic只创建了4个队列,反复重试确认发送消息时自动创建Topic,最大创建4个队列。

 

int queueNums = clientDefaultTopicQueueNums > defaultTopicConfig.getWriteQueueNums() ? defaultTopicConfig.getWriteQueueNums() : clientDefaultTopicQueueNums;

查找原因

服务端与客户端配置对比

    阅读源码,在TopicConfigManagercreateTopicInSendMessageMethod方法,有对比TopicConfig对象中的队列数和客户端设定队列数,并选择其中较小者为新建Topic队列数的逻辑:


 

定位问题在服务端TopicConfig

打印这两个变量:

客户队列数clientDefaultTopicQueueNums8,正确;

defaultTopicConfig.getWriteQueueNums()4,而非broker.properties中设定的16

 

由可以确定是问题出在defaultTopicConfig上。

 

defaultTopicConfig数据来源

    defaultTopicConfig是从ConcurrentHashMap<String,TopicConfig> topicConfigTable中取得,如下:

TopicConfig defaultTopicConfig =this.topicConfigTable.get(defaultTopic);

 

defaultTopic默认值为MixAll.DEFAULT_TOPIC=TBW102”。

 

    为了确认topicConfigTable中的为MixAll.DEFAULT_TOPICConfig对象属性值的真实来源,继续阅读源码,发现borker有两处改写DEFAULT_TOPICConfig对象的位置:


    一处是TopicConfigManager的构造方法,在borker服务器启动时运行,会读取broker.properties里的配置,此时DEFAULT_TOPICConfig对象里的DefaultQueueNums为正确的我所配置的16;


    一处是在BrokerControllerinitialize方法里调用了TopicConfigManager.load方法:

    load方法继承自ConfigManager类,读取了$ROCKETMQ_HOME\store\config下保存的配置信息,并调用抽象方法decode(),配置信息作为json字符串参数传入到decode();

    TopicConfigManager类的decode实现方法里,读取了$ROCKETMQ_HOME\store\config\topics.json里的配置信息,并覆写到topicConfigTable,而此前生成的topics.json的“TBW102”的配置信息里的writeQueueNumsreadQueueNums均为4

 

最终结论

    在发送消息自动创建Topic时,对于此前已运行的borker服务器,修改配置文件的defaultTopicQueueNums属性的值不起作用。

    因为发送消息自动创建Topic的实现里,队列数取小对比操作的变量——defaultTopicConfig写在topics.json的配置信息里的writeQueueNumsreadQueueNums,读取自Topics.json,所以即使修改配置文件并重启borker服务器后也不会改变。而服务端最终会用topics.json的值覆盖发送消息自动创建Topic时的TopicConfig配置信息。

 

阿里的解释

    队列是资源,所以管控权会放到服务器。

    但是每个用户的默认策略又不一样,所以会有一个默认topic作为模板,在未创建默认topic前,系统会自动创建一个。

    这个可以占到运维的角度思考,例如你运维了10个集群,为1000个用户服务。有些用户需要动态的创建topic,但是不能给他足够的权限,想创建多少创建多少。

    所有会给他一个模板的topic,就是defaultTopic,动态创建topic继承于defaultTopic配置,队列数不能超过defaultTopic

 

解决办法


  • 通过producer.createTopic方法创建(实现的方式是将创建命发送到控制台),可以创建成功,但会报应答超时失败,原因未查;

  • 通过控制台方式创建;

  • 修改metaq源码重新编译borker,使用broker的配置信息覆盖defaultTopic的配置信息。


本文出自 “赞否两论-量子” 博客,请务必保留此出处http://quantum.blog.51cto.com/3633234/1581076

RocketMQ3.2.2生产者发送消息自动创建Topic队列数无法超过4个