首页 > 代码库 > 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;
查找原因
服务端与客户端配置对比
阅读源码,在TopicConfigManager的createTopicInSendMessageMethod方法,有对比TopicConfig对象中的队列数和客户端设定队列数,并选择其中较小者为新建Topic队列数的逻辑:
定位问题在服务端TopicConfig
打印这两个变量:
客户队列数clientDefaultTopicQueueNums为8,正确;
而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_TOPIC的Config对象属性值的真实来源,继续阅读源码,发现borker有两处改写DEFAULT_TOPIC的Config对象的位置:
一处是TopicConfigManager的构造方法,在borker服务器启动时运行,会读取broker.properties里的配置,此时DEFAULT_TOPIC的Config对象里的DefaultQueueNums为正确的我所配置的16;
一处是在BrokerController的initialize方法里调用了TopicConfigManager.load方法:
该load方法继承自ConfigManager类,读取了$ROCKETMQ_HOME\store\config下保存的配置信息,并调用抽象方法decode(),配置信息作为json字符串参数传入到decode();
TopicConfigManager类的decode实现方法里,读取了$ROCKETMQ_HOME\store\config\topics.json里的配置信息,并覆写到topicConfigTable,而此前生成的topics.json的“TBW102”的配置信息里的writeQueueNums及readQueueNums均为4。
最终结论
在发送消息自动创建Topic时,对于此前已运行的borker服务器,修改配置文件的defaultTopicQueueNums属性的值不起作用。
因为发送消息自动创建Topic的实现里,队列数取小对比操作的变量——defaultTopicConfig写在topics.json的配置信息里的writeQueueNums及readQueueNums,读取自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个