引用 (2條消息) rocketmq問題匯總-instanceName參數何時該設置?_MQCloud的專欄-CSDN博客
1 producer
默認情況下不需要設置instanceName,rocketmq會使用ip@pid(pid代表jvm名字)作為唯一標示
如果同一個jvm中,不同的producer需要往不同的rocketmq集群發送消息,需要設置不同的instanceName
原因如下:如果不設置instanceName,那么會使用ip@pid作為producer唯一標識,那么會導致多個producer內部只有一個MQClientInstance(與mq交互)實例,從而導致只往一個集群發消息。
2 consumer
默認情況下不需要設置instanceName,rocketmq會使用ip@pid作為instanceName(pid代表jvm名字)
如果設置instanceName,rocketmq會使用ip@instanceName作為consumer的唯一標示,此時需要注意instanceName需要不同。
如果consumer設置了instanceName,如果是多台主機上,每一台主機一個JVM進程,這種情況還好。如果是一台主機上,多個JVM進程,且每個consumer的instanceName還相同的情況下,就會出現只有一台consumer消費全部消息的情況。
因為 rocketmq會使用ip@instanceName作為consumer的唯一標示,這樣多個JVM進程中的consumer只有一種cid
這樣在rebalance過程中,會導致只有一個consumer消費所有messagequeue
AllocateMessageQueueAveragely # allocate
public List<MessageQueue> allocate(String consumerGroup, String currentCID, List<MessageQueue> mqAll, List<String> cidAll) { if (currentCID == null || currentCID.length() < 1) { throw new IllegalArgumentException("currentCID is empty"); } if (mqAll == null || mqAll.isEmpty()) { throw new IllegalArgumentException("mqAll is null or mqAll empty"); } if (cidAll == null || cidAll.isEmpty()) { throw new IllegalArgumentException("cidAll is null or cidAll empty"); } List<MessageQueue> result = new ArrayList<MessageQueue>(); if (!cidAll.contains(currentCID)) { log.info("[BUG] ConsumerGroup: {} The consumerId: {} not in cidAll: {}", consumerGroup, currentCID, cidAll); return result; } int index = cidAll.indexOf(currentCID); int mod = mqAll.size() % cidAll.size();//cidAll實際只有一個成員 mod 就是0 int averageSize = mqAll.size() <= cidAll.size() ? 1 : (mod > 0 && index < mod ? mqAll.size() / cidAll.size() + 1 : mqAll.size() / cidAll.size()); int startIndex = (mod > 0 && index < mod) ? index * averageSize : index * averageSize + mod;//startIndex就是0 int range = Math.min(averageSize, mqAll.size() - startIndex); for (int i = 0; i < range; i++) { result.add(mqAll.get((startIndex + i) % mqAll.size())); } return result; }
這樣就是永遠一個consumer消費了所有messageQueue。
不過這種情況也比較極端,一台主機跑一個系統下的多個JVM這不多見
