关于配置的InstanceName问题
默认InstanceName为DEFAULT
客户端启动后在集群模式下会修改为ip@pid 。
public void changeInstanceNameToPID() {
if (this.instanceName.equals("DEFAULT")) {
this.instanceName = String.valueOf(UtilAll.getPid()); }
}
public String buildMQClientId() {
StringBuilder sb = new StringBuilder();
sb.append(this.getClientIP());
sb.append("@");
sb.append(this.getInstanceName());
return sb.toString();
}
同一个InstanceName 会使用 同一个MQClientInstance,MQClientInstance 负责与rocketmq交互。
this.mQClientFactory =
MQClientManager.getInstance().getAndCreateMQClientInstance(this.defaultMQPushConsumer, this.rpcHook);
对同InstanceName的不同生产者消费者对象,使用一个hashmap存储
//对于消费者
boolean registerOK =
mQClientFactory.registerConsumer(this.defaultMQPushConsumer.getConsumerGroup(), this);
//对于生产者
boolean registerOK =
mQClientFactory.registerProducer(this.defaultMQProducer.getProducerGroup(), this);
有相同group和InstanceName 两个消费者或者两个生产者时会发送冲突。报出异常
com.alibaba.rocketmq.client.exception.MQClientException: The consumer group[1] has been created before, specify another name please.
后启动的生产者或消费者会启动失败然后失效。
InstanceName 的作用
当多个生产者消费者对象使用同一个InstanceName 时,那么他们使用的是同一个MQClientInstance ,这样一些异步线程,定时拉取topic,心跳,nettyclient等线程都是一份,可以节省资源。
用于负载均衡
消费者在负载均衡时使用InstanceName 做区分。如果在同一ip下,两个服务中的消费者使用的同样的配置。InstanceName 一样。
比如 两个都叫 10.2.116.119@bbbbb 。这样负载均衡会认为是同一个消费者。比如他把4个MessageQueue 分个10.2.116.119@bbbbb 。那么两个10.2.116.119@bbbbb 的实例都可以消费这4个MessageQueue 。
本来的集群消费,就会变成像广播消费一样重复消费,并发生混乱
配置方法:同一jvm实例内如果都访问同一集群。那么尽量用同一InstanceName 。
一个消费者或者生产者的group只能有一个生产者或者消费者对象
同一ip下的不同jvm实例不能使用同一个InstanceName,不同ip可以