tju-yxq opened a new issue, #1428: URL: https://github.com/apache/rocketmq-dashboard/issues/1428
## Bug Report ### Before Creating the Bug Report - [x] I found a bug, not just asking a question, which should be created in [GitHub Discussions](https://github.com/apache/rocketmq/discussions). - [x] I have searched the [GitHub Issues](https://github.com/apache/rocketmq/issues) and [GitHub Discussions](https://github.com/apache/rocketmq/discussions) of this repository and believe that this is not a duplicate. - [x] I have confirmed that this bug belongs to the current repository, not other repositories of RocketMQ. ### Runtime platform environment OS: Ubuntu 20.04 / Any OS running RocketMQ Studio ### RocketMQ version branch: rocketmq-studio version: 5.3.2+ Git commit id: f727341 ### JDK Version OpenJDK 21 ### Describe the Bug `RocketMQAdminClientImpl.getAllMasterBrokerAddrs()` returns **all** master broker addresses from the entire NameServer topology, regardless of which cluster they belong to. When `createTopic`, `updateTopic`, or `createConsumerGroup` call this method, the topic/group config is pushed to **every broker across all clusters**, not just the target cluster. ```java private Set<String> getAllMasterBrokerAddrs(MQAdminExt admin) throws Exception { Set<String> addrs = new HashSet<>(); ClusterInfo clusterInfo = admin.examineBrokerClusterInfo(); // ... iterates ALL brokers in brokerAddrTable, not filtered by cluster for (BrokerData brokerData : clusterInfo.getBrokerAddrTable().values()) { String masterAddr = brokerData.getBrokerAddrs().get(0L); if (masterAddr != null) { addrs.add(masterAddr); } } return addrs; } ``` Meanwhile, `getClusterName()` returns only the **first** cluster name from `clusterAddrTable.keySet().iterator().next()`, so the DB record is associated with just one cluster while the broker-side config is spread to all clusters. ### Impact In a NameServer managing multiple clusters (e.g., `DefaultCluster` and `BatchCluster`): 1. Creating a topic for `DefaultCluster` also creates it on `BatchCluster`'s brokers. 2. Creating a consumer group for `DefaultCluster` also registers it on `BatchCluster`'s brokers. 3. Deleting a topic calls `deleteTopicInBroker` with all broker addresses, removing it from all clusters. 4. The DB record only tracks the first cluster, so the UI shows the topic/group for only one cluster while it actually exists on all. ### Steps to Reproduce 1. Configure a RocketMQ NameServer managing two clusters: `clusterA` (brokers: `broker-a1`, `broker-a2`) and `clusterB` (brokers: `broker-b1`, `broker-b2`). 2. In RocketMQ Studio, create a topic `test-topic` targeting `clusterA`. 3. Check `clusterB`'s brokers: `mqadmin topicList -b broker-b1:10911` - `test-topic` is present even though it was only meant for `clusterA`. 4. The Studio DB record associates `test-topic` with `clusterA` (the first cluster returned by `getClusterName`). ### What Did You Expect to See? Topic and consumer group operations should only target brokers belonging to the specified cluster, using the `clusterAddrTable` to map cluster name to broker names and then to broker addresses. ### What Did You See Instead? Topics and groups are created on all brokers across all clusters managed by the NameServer. ### Additional Context **Affected file**: `server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQAdminClientImpl.java`, method `getAllMasterBrokerAddrs()` at approximately line 500. **Related issues**: #1167, #1243, #1131 address instance routing (which NameServer to connect to), but this bug is different: even when connected to the correct NameServer, the code pushes config to all clusters instead of the target cluster. **Fix approach**: Add an overload that filters brokers by cluster name: ```java private Set<String> getMasterBrokerAddrsForCluster(MQAdminExt admin, String clusterName) throws Exception { Set<String> addrs = new HashSet<>(); ClusterInfo clusterInfo = admin.examineBrokerClusterInfo(); if (clusterInfo == null || clusterInfo.getClusterAddrTable() == null) { return addrs; } Set<String> brokerNames = clusterInfo.getClusterAddrTable().get(clusterName); if (brokerNames == null || clusterInfo.getBrokerAddrTable() == null) { return addrs; } for (String brokerName : brokerNames) { BrokerData brokerData = clusterInfo.getBrokerAddrTable().get(brokerName); if (brokerData != null && brokerData.getBrokerAddrs() != null) { String masterAddr = brokerData.getBrokerAddrs().get(0L); if (masterAddr == null && !brokerData.getBrokerAddrs().isEmpty()) { masterAddr = brokerData.getBrokerAddrs().values().iterator().next(); } if (masterAddr != null) { addrs.add(masterAddr); } } } return addrs; } ``` Then update `createTopic`, `updateTopic`, `createConsumerGroup`, `deleteConsumerGroup`, and `deleteTopic` to use the cluster-scoped method with the cluster name from `getClusterName()`. The existing `getAllMasterBrokerAddrs` can be kept as a fallback for single-cluster deployments. This adds approximately 25 lines (the new method) and modifies 4-5 call sites, totaling ~35 lines of changes. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
