美文网首页
RocketMq创建ConsumeQueue的个数

RocketMq创建ConsumeQueue的个数

作者: 运维开发笔记 | 来源:发表于2017-10-12 09:10 被阅读0次

    问题现象
    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的配置信息。

    相关文章

      网友评论

          本文标题:RocketMq创建ConsumeQueue的个数

          本文链接:https://www.haomeiwen.com/subject/rpkbsxtx.html