RocketMQ 之 instanceName (二)

367 阅读2分钟

接着上篇文章我们,我们说了 MQClientId ,MQClientInstance是一个比较重要的概念,那么这个到底用在那个地方了呢?

我们先记住MQClientInstance是与MQ broken进行交互的载体,我们再来下面获取MQClientInstance的方式.

public MQClientInstance getOrCreateMQClientInstance(final ClientConfig clientConfig, RPCHook rpcHook) {
    //获取MqClientId,此处我们发现 MQClientId在生成MQClientInstance需要用到
    String clientId = clientConfig.buildMQClientId();
    /*
     * factoryTable是一个ConcurrentMap的结果,key就是 MQClientId
     */
    MQClientInstance instance = this.factoryTable.get(clientId);
    if (null == instance) {
        instance =
            new MQClientInstance(clientConfig.cloneClientConfig(),
                this.factoryIndexGenerator.getAndIncrement(), clientId, rpcHook);
        MQClientInstance prev = this.factoryTable.putIfAbsent(clientId, instance);
        if (prev != null) {
            instance = prev;
            log.warn("Returned Previous MQClientInstance for clientId:[{}]", clientId);
        } else {
            log.info("Created new MQClientInstance for clientId:[{}]", clientId);
        }
    }
    return instance;
}

配合代码里的注释,所以当我们需要获取MQClientInstance对象与broker进行交互的时候,那我们我们就先需要先获取MQClientInstance ,那么如果获取MQClientInstance, MQClientInstance存放在一个类似Map的结构提里, MQClientId 就是获取MQClientInstance的key.

所以我们回顾一下,上篇文章中写的RocketMQ在4.9.0以上及一下版本获取MQClientId的差异,我们可以假设一下场景:

我们先假设RocketMQ的版本是4.9.0一下,那么我们再看看4.9.0以下的版本

public void changeInstanceNameToPID() {
    if (this.instanceName.equals("DEFAULT")) {
        this.instanceName = String.valueOf(UtilAll.getPid());    
    }
}

假如我们的项目里配置了2个以上的MQ集群,当我们没有主动设置instanceName的时候,我们会发现,生成的MQClientId是一样,而存放MQClientInstance是一个map接口,如果key是一样的,那么就意味着,程序里虽然配置里2个MQ集群,但是实际上MAP里却只有一个MQClientInstance,所以当我们在使用RocketMQ-4.9.0以下版本的时候, 且项目里配置了2个及以上MQ集群的时候,一定要配置instanceName属性, 所以我还是建议在4.9.0以下版本的时候,都配置上instanceName属性.

我们再看看4.9.0及以上版本的变化.

public void changeInstanceNameToPID() {
    if (this.instanceName.equals("DEFAULT")) {
        this.instanceName = UtilAll.getPid() + "#" + System.nanoTime();
    }
}

其实4.9.0及以上的版本,就是在InstanceName后面加了一个时间戳. 其实这样就可以避免当我们没有设置instanceName的时候,且项目里配置了2个及以上MQ集群的时候,最后根据instanceName生成MQClientID的时候,不会出现相同的MQClientId.

总结

在同一个工程里,一个MQ集群就只需要一个MQ Producer. 如果MQ集群是根据BU划分的话,MQ Producer的命名最好跟BU名保持一致,切记不要涉及到要发消息,自己就新建一个跟业务名称相关的Producer, 这样除了占用内存之外,并无其他用户.