mirror of
https://github.com/apache/rocketmq-dashboard.git
synced 2026-02-23 22:55:46 +08:00
Compare commits
5 Commits
dependabot
...
01e5fcb1b4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01e5fcb1b4 | ||
|
|
21dc2acfdc | ||
|
|
823bce2b8b | ||
|
|
2fb0fce0b1 | ||
|
|
a4a6000734 |
1
.dockerignore
Normal file
1
.dockerignore
Normal file
@@ -0,0 +1 @@
|
||||
target/
|
||||
@@ -15,9 +15,16 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
FROM java:8
|
||||
VOLUME /tmp
|
||||
ADD rocketmq-dashboard-*.jar rocketmq-dashboard.jar
|
||||
RUN sh -c 'touch /rocketmq-dashboard.jar'
|
||||
ENV JAVA_OPTS=""
|
||||
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -jar /rocketmq-dashboard.jar" ]
|
||||
FROM maven:3.8.6-openjdk-8 AS builder
|
||||
|
||||
ADD . .
|
||||
|
||||
# package jar
|
||||
RUN mvn clean package -Dmaven.test.skip=true
|
||||
|
||||
FROM openjdk:8u342-jdk
|
||||
|
||||
# copy jar from the builder stage
|
||||
COPY --from=builder target/rocketmq-dashboard-*.jar rocketmq-dashboard.jar
|
||||
|
||||
ENTRYPOINT exec java $JAVA_OPTS -jar rocketmq-dashboard.jar
|
||||
|
||||
@@ -56,6 +56,12 @@ public class TopicController {
|
||||
return topicService.fetchAllTopicList(skipSysProcess, skipRetryAndDlq);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/list.queryTopicType", method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public Object listTopicType() {
|
||||
return topicService.examineAllTopicType();
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/stats.query", method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public Object stats(@RequestParam String topic) {
|
||||
|
||||
@@ -31,6 +31,7 @@ public class TopicConfigInfo {
|
||||
private int perm;
|
||||
private boolean order;
|
||||
|
||||
private String messageType;
|
||||
public List<String> getClusterNameList() {
|
||||
return clusterNameList;
|
||||
}
|
||||
@@ -91,6 +92,18 @@ public class TopicConfigInfo {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
|
||||
public String getMessageType() {
|
||||
return messageType;
|
||||
}
|
||||
|
||||
public void setMessageType(String messageType) {
|
||||
this.messageType = messageType;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
@@ -102,12 +115,13 @@ public class TopicConfigInfo {
|
||||
readQueueNums == that.readQueueNums &&
|
||||
perm == that.perm &&
|
||||
order == that.order &&
|
||||
Objects.equal(topicName, that.topicName);
|
||||
Objects.equal(topicName, that.topicName) &&
|
||||
Objects.equal(messageType, that.messageType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(topicName, writeQueueNums, readQueueNums, perm, order);
|
||||
return Objects.hashCode(topicName, writeQueueNums, readQueueNums, perm, order,messageType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.rocketmq.dashboard.model.request;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TopicTypeList {
|
||||
private List<String> topicNameList;
|
||||
private List<String> messageTypeList;
|
||||
|
||||
public List<String> getTopicNameList() {
|
||||
return topicNameList;
|
||||
}
|
||||
|
||||
public void setTopicNameList(List<String> topicNameList) {
|
||||
this.topicNameList = topicNameList;
|
||||
}
|
||||
|
||||
public List<String> getMessageTypeList() {
|
||||
return messageTypeList;
|
||||
}
|
||||
|
||||
public void setMessageTypeList(List<String> messageTypeList) {
|
||||
this.messageTypeList = messageTypeList;
|
||||
}
|
||||
|
||||
public TopicTypeList(List<String> topicNameList, List<String> messageTypeList) {
|
||||
this.topicNameList = topicNameList;
|
||||
this.messageTypeList = messageTypeList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.rocketmq.dashboard.model.request;
|
||||
|
||||
public class TopicTypeMeta {
|
||||
private String topicName;
|
||||
private String messageType;
|
||||
|
||||
public String getTopicName() {
|
||||
return topicName;
|
||||
}
|
||||
|
||||
public void setTopicName(String topicName) {
|
||||
this.topicName = topicName;
|
||||
}
|
||||
|
||||
public String getMessageType() {
|
||||
return messageType;
|
||||
}
|
||||
|
||||
public void setMessageType(String messageType) {
|
||||
this.messageType = messageType;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package org.apache.rocketmq.dashboard.service;
|
||||
|
||||
import org.apache.rocketmq.client.producer.SendResult;
|
||||
import org.apache.rocketmq.common.TopicConfig;
|
||||
import org.apache.rocketmq.dashboard.model.request.TopicTypeList;
|
||||
import org.apache.rocketmq.remoting.protocol.admin.TopicStatsTable;
|
||||
import org.apache.rocketmq.remoting.protocol.body.GroupList;
|
||||
import org.apache.rocketmq.remoting.protocol.body.TopicList;
|
||||
@@ -31,6 +32,8 @@ import java.util.List;
|
||||
public interface TopicService {
|
||||
TopicList fetchAllTopicList(boolean skipSysProcess, boolean skipRetryAndDlq);
|
||||
|
||||
TopicTypeList examineAllTopicType();
|
||||
|
||||
TopicStatsTable stats(String topic);
|
||||
|
||||
TopicRouteData route(String topic);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package org.apache.rocketmq.dashboard.service.impl;
|
||||
|
||||
import org.apache.rocketmq.common.attribute.TopicMessageType;
|
||||
import org.apache.rocketmq.remoting.protocol.body.ClusterInfo;
|
||||
import org.apache.rocketmq.remoting.protocol.body.KVTable;
|
||||
import org.apache.rocketmq.remoting.protocol.route.BrokerData;
|
||||
@@ -30,8 +31,10 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class ClusterServiceImpl implements ClusterService {
|
||||
@@ -56,6 +59,9 @@ public class ClusterServiceImpl implements ClusterService {
|
||||
}
|
||||
resultMap.put("clusterInfo", clusterInfo);
|
||||
resultMap.put("brokerServer", brokerServer);
|
||||
// add messageType
|
||||
resultMap.put("messageTypes", Arrays.stream(TopicMessageType.values()).sorted()
|
||||
.collect(Collectors.toMap(TopicMessageType::getValue, messageType ->String.format("MESSAGE_TYPE_%s",messageType.getValue()))));
|
||||
return resultMap;
|
||||
}
|
||||
catch (Exception err) {
|
||||
|
||||
@@ -18,43 +18,57 @@
|
||||
package org.apache.rocketmq.dashboard.service.impl;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.rocketmq.acl.common.AclClientRPCHook;
|
||||
import org.apache.rocketmq.acl.common.SessionCredentials;
|
||||
import org.apache.rocketmq.client.producer.DefaultMQProducer;
|
||||
import org.apache.rocketmq.client.producer.SendResult;
|
||||
import org.apache.rocketmq.client.producer.TransactionListener;
|
||||
import org.apache.rocketmq.client.producer.TransactionMQProducer;
|
||||
import org.apache.rocketmq.client.producer.LocalTransactionState;
|
||||
import org.apache.rocketmq.client.trace.TraceContext;
|
||||
import org.apache.rocketmq.client.trace.TraceDispatcher;
|
||||
import org.apache.rocketmq.common.MixAll;
|
||||
import org.apache.rocketmq.common.TopicConfig;
|
||||
import org.apache.rocketmq.remoting.protocol.admin.TopicStatsTable;
|
||||
import org.apache.rocketmq.common.attribute.TopicMessageType;
|
||||
import org.apache.rocketmq.common.message.Message;
|
||||
import org.apache.rocketmq.common.message.MessageExt;
|
||||
import org.apache.rocketmq.common.topic.TopicValidator;
|
||||
import org.apache.rocketmq.dashboard.config.RMQConfigure;
|
||||
import org.apache.rocketmq.dashboard.model.request.SendTopicMessageRequest;
|
||||
import org.apache.rocketmq.dashboard.model.request.TopicConfigInfo;
|
||||
import org.apache.rocketmq.dashboard.model.request.TopicTypeList;
|
||||
import org.apache.rocketmq.dashboard.model.request.TopicTypeMeta;
|
||||
import org.apache.rocketmq.dashboard.service.AbstractCommonService;
|
||||
import org.apache.rocketmq.dashboard.service.TopicService;
|
||||
import org.apache.rocketmq.remoting.RPCHook;
|
||||
import org.apache.rocketmq.remoting.protocol.admin.TopicStatsTable;
|
||||
import org.apache.rocketmq.remoting.protocol.body.ClusterInfo;
|
||||
import org.apache.rocketmq.remoting.protocol.body.GroupList;
|
||||
import org.apache.rocketmq.remoting.protocol.body.TopicList;
|
||||
import org.apache.rocketmq.remoting.protocol.route.BrokerData;
|
||||
import org.apache.rocketmq.remoting.protocol.route.TopicRouteData;
|
||||
import org.apache.rocketmq.common.topic.TopicValidator;
|
||||
import org.apache.rocketmq.dashboard.config.RMQConfigure;
|
||||
import org.apache.rocketmq.dashboard.model.request.SendTopicMessageRequest;
|
||||
import org.apache.rocketmq.dashboard.model.request.TopicConfigInfo;
|
||||
import org.apache.rocketmq.dashboard.service.AbstractCommonService;
|
||||
import org.apache.rocketmq.dashboard.service.TopicService;
|
||||
import org.apache.rocketmq.remoting.RPCHook;
|
||||
import org.apache.rocketmq.tools.command.CommandUtil;
|
||||
import org.joor.Reflect;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.rocketmq.common.TopicAttributes.TOPIC_MESSAGE_TYPE_ATTRIBUTE;
|
||||
|
||||
@Service
|
||||
public class TopicServiceImpl extends AbstractCommonService implements TopicService {
|
||||
@@ -68,18 +82,18 @@ public class TopicServiceImpl extends AbstractCommonService implements TopicServ
|
||||
TopicList allTopics = mqAdminExt.fetchAllTopicList();
|
||||
TopicList sysTopics = getSystemTopicList();
|
||||
Set<String> topics =
|
||||
allTopics.getTopicList().stream().map(topic -> {
|
||||
if (!skipSysProcess && sysTopics.getTopicList().contains(topic)) {
|
||||
topic = String.format("%s%s", "%SYS%", topic);
|
||||
}
|
||||
return topic;
|
||||
}).filter(topic -> {
|
||||
if (skipRetryAndDlq) {
|
||||
return !(topic.startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)
|
||||
|| topic.startsWith(MixAll.DLQ_GROUP_TOPIC_PREFIX));
|
||||
}
|
||||
return true;
|
||||
}).collect(Collectors.toSet());
|
||||
allTopics.getTopicList().stream().map(topic -> {
|
||||
if (!skipSysProcess && sysTopics.getTopicList().contains(topic)) {
|
||||
topic = String.format("%s%s", "%SYS%", topic);
|
||||
}
|
||||
return topic;
|
||||
}).filter(topic -> {
|
||||
if (skipRetryAndDlq) {
|
||||
return !(topic.startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)
|
||||
|| topic.startsWith(MixAll.DLQ_GROUP_TOPIC_PREFIX));
|
||||
}
|
||||
return true;
|
||||
}).collect(Collectors.toSet());
|
||||
allTopics.getTopicList().clear();
|
||||
allTopics.getTopicList().addAll(topics);
|
||||
return allTopics;
|
||||
@@ -89,6 +103,41 @@ public class TopicServiceImpl extends AbstractCommonService implements TopicServ
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TopicTypeList examineAllTopicType() {
|
||||
ArrayList<TopicTypeMeta> topicTypes = new ArrayList<>();
|
||||
ArrayList<String> names = new ArrayList<>();
|
||||
ArrayList<String> messageTypes = new ArrayList<>();
|
||||
TopicList topicList = fetchAllTopicList(false, false);
|
||||
checkTopicType(topicList, topicTypes);
|
||||
topicTypes.sort((t1, t2) -> t1.getTopicName().compareTo(t2.getTopicName()));
|
||||
for (TopicTypeMeta topicTypeMeta : topicTypes) {
|
||||
names.add(topicTypeMeta.getTopicName());
|
||||
messageTypes.add(topicTypeMeta.getMessageType());
|
||||
}
|
||||
return new TopicTypeList(names, messageTypes);
|
||||
}
|
||||
|
||||
private void checkTopicType(TopicList topicList, ArrayList<TopicTypeMeta> topicTypes) {
|
||||
for (String topicName : topicList.getTopicList()) {
|
||||
TopicTypeMeta topicType = new TopicTypeMeta();
|
||||
topicType.setTopicName(topicName);
|
||||
if (topicName.startsWith("%R")) {
|
||||
topicType.setMessageType("RETRY");
|
||||
} else if (topicName.startsWith("%D")) {
|
||||
topicType.setMessageType("DELAY");
|
||||
} else if (topicName.startsWith("%S")) {
|
||||
topicType.setMessageType("SYSTEM");
|
||||
} else {
|
||||
List<TopicConfigInfo> topicConfigInfos = examineTopicConfig(topicName);
|
||||
if (!CollectionUtils.isEmpty(topicConfigInfos)) {
|
||||
topicType.setMessageType(topicConfigInfos.get(0).getMessageType());
|
||||
}
|
||||
}
|
||||
topicTypes.add(topicType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TopicStatsTable stats(String topic) {
|
||||
try {
|
||||
@@ -123,10 +172,15 @@ public class TopicServiceImpl extends AbstractCommonService implements TopicServ
|
||||
public void createOrUpdate(TopicConfigInfo topicCreateOrUpdateRequest) {
|
||||
TopicConfig topicConfig = new TopicConfig();
|
||||
BeanUtils.copyProperties(topicCreateOrUpdateRequest, topicConfig);
|
||||
String messageType = topicCreateOrUpdateRequest.getMessageType();
|
||||
if (StringUtils.isBlank(messageType)) {
|
||||
messageType = TopicMessageType.NORMAL.name();
|
||||
}
|
||||
topicConfig.setAttributes(ImmutableMap.of("+".concat(TOPIC_MESSAGE_TYPE_ATTRIBUTE.getName()), messageType));
|
||||
try {
|
||||
ClusterInfo clusterInfo = mqAdminExt.examineBrokerClusterInfo();
|
||||
for (String brokerName : changeToBrokerNameSet(clusterInfo.getClusterAddrTable(),
|
||||
topicCreateOrUpdateRequest.getClusterNameList(), topicCreateOrUpdateRequest.getBrokerNameList())) {
|
||||
topicCreateOrUpdateRequest.getClusterNameList(), topicCreateOrUpdateRequest.getBrokerNameList())) {
|
||||
mqAdminExt.createAndUpdateTopicConfig(clusterInfo.getBrokerAddrTable().get(brokerName).selectBrokerAddr(), topicConfig);
|
||||
}
|
||||
} catch (Exception err) {
|
||||
@@ -156,6 +210,11 @@ public class TopicServiceImpl extends AbstractCommonService implements TopicServ
|
||||
TopicConfig topicConfig = examineTopicConfig(topic, brokerData.getBrokerName());
|
||||
BeanUtils.copyProperties(topicConfig, topicConfigInfo);
|
||||
topicConfigInfo.setBrokerNameList(Lists.newArrayList(brokerData.getBrokerName()));
|
||||
String messageType = topicConfig.getAttributes().get(TOPIC_MESSAGE_TYPE_ATTRIBUTE.getName());
|
||||
if (StringUtils.isBlank(messageType)) {
|
||||
messageType = TopicMessageType.UNSPECIFIED.name();
|
||||
}
|
||||
topicConfigInfo.setMessageType(messageType);
|
||||
topicConfigInfoList.add(topicConfigInfo);
|
||||
}
|
||||
return topicConfigInfoList;
|
||||
@@ -226,6 +285,12 @@ public class TopicServiceImpl extends AbstractCommonService implements TopicServ
|
||||
return defaultMQProducer;
|
||||
}
|
||||
|
||||
public TransactionMQProducer buildTransactionMQProducer(String producerGroup, RPCHook rpcHook, boolean traceEnabled) {
|
||||
TransactionMQProducer defaultMQProducer = new TransactionMQProducer(null, producerGroup, rpcHook, traceEnabled, TopicValidator.RMQ_SYS_TRACE_TOPIC);
|
||||
defaultMQProducer.setUseTLS(configure.isUseTLS());
|
||||
return defaultMQProducer;
|
||||
}
|
||||
|
||||
private TopicList getSystemTopicList() {
|
||||
RPCHook rpcHook = null;
|
||||
boolean isEnableAcl = !StringUtils.isEmpty(configure.getAccessKey()) && !StringUtils.isEmpty(configure.getSecretKey());
|
||||
@@ -249,32 +314,61 @@ public class TopicServiceImpl extends AbstractCommonService implements TopicServ
|
||||
|
||||
@Override
|
||||
public SendResult sendTopicMessageRequest(SendTopicMessageRequest sendTopicMessageRequest) {
|
||||
DefaultMQProducer producer = null;
|
||||
List<TopicConfigInfo> topicConfigInfos = examineTopicConfig(sendTopicMessageRequest.getTopic());
|
||||
String messageType = topicConfigInfos.get(0).getMessageType();
|
||||
AclClientRPCHook rpcHook = null;
|
||||
if (configure.isACLEnabled()) {
|
||||
rpcHook = new AclClientRPCHook(new SessionCredentials(
|
||||
configure.getAccessKey(),
|
||||
configure.getSecretKey()
|
||||
configure.getAccessKey(),
|
||||
configure.getSecretKey()
|
||||
));
|
||||
}
|
||||
producer = buildDefaultMQProducer(MixAll.SELF_TEST_PRODUCER_GROUP, rpcHook, sendTopicMessageRequest.isTraceEnabled());
|
||||
producer.setInstanceName(String.valueOf(System.currentTimeMillis()));
|
||||
producer.setNamesrvAddr(configure.getNamesrvAddr());
|
||||
try {
|
||||
producer.start();
|
||||
Message msg = new Message(sendTopicMessageRequest.getTopic(),
|
||||
sendTopicMessageRequest.getTag(),
|
||||
sendTopicMessageRequest.getKey(),
|
||||
sendTopicMessageRequest.getMessageBody().getBytes()
|
||||
);
|
||||
return producer.send(msg);
|
||||
} catch (Exception e) {
|
||||
Throwables.throwIfUnchecked(e);
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
waitSendTraceFinish(producer, sendTopicMessageRequest.isTraceEnabled());
|
||||
producer.shutdown();
|
||||
if (TopicMessageType.TRANSACTION.getValue().equals(messageType)) {
|
||||
// transaction message
|
||||
TransactionListener transactionListener = new TransactionListenerImpl();
|
||||
|
||||
TransactionMQProducer producer = buildTransactionMQProducer(MixAll.SELF_TEST_PRODUCER_GROUP, rpcHook, sendTopicMessageRequest.isTraceEnabled());
|
||||
producer.setInstanceName(String.valueOf(System.currentTimeMillis()));
|
||||
producer.setNamesrvAddr(configure.getNamesrvAddr());
|
||||
producer.setTransactionListener(transactionListener);
|
||||
try {
|
||||
producer.start();
|
||||
Message msg = new Message(sendTopicMessageRequest.getTopic(),
|
||||
sendTopicMessageRequest.getTag(),
|
||||
sendTopicMessageRequest.getKey(),
|
||||
sendTopicMessageRequest.getMessageBody().getBytes()
|
||||
);
|
||||
return producer.sendMessageInTransaction(msg, null);
|
||||
} catch (Exception e) {
|
||||
Throwables.throwIfUnchecked(e);
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
waitSendTraceFinish(producer, sendTopicMessageRequest.isTraceEnabled());
|
||||
producer.shutdown();
|
||||
}
|
||||
} else {
|
||||
// no transaction message
|
||||
DefaultMQProducer producer = null;
|
||||
producer = buildDefaultMQProducer(MixAll.SELF_TEST_PRODUCER_GROUP, rpcHook, sendTopicMessageRequest.isTraceEnabled());
|
||||
producer.setInstanceName(String.valueOf(System.currentTimeMillis()));
|
||||
producer.setNamesrvAddr(configure.getNamesrvAddr());
|
||||
try {
|
||||
producer.start();
|
||||
Message msg = new Message(sendTopicMessageRequest.getTopic(),
|
||||
sendTopicMessageRequest.getTag(),
|
||||
sendTopicMessageRequest.getKey(),
|
||||
sendTopicMessageRequest.getMessageBody().getBytes()
|
||||
);
|
||||
return producer.send(msg);
|
||||
} catch (Exception e) {
|
||||
Throwables.throwIfUnchecked(e);
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
waitSendTraceFinish(producer, sendTopicMessageRequest.isTraceEnabled());
|
||||
producer.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void waitSendTraceFinish(DefaultMQProducer producer, boolean traceEnabled) {
|
||||
@@ -296,4 +390,20 @@ public class TopicServiceImpl extends AbstractCommonService implements TopicServ
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
static class TransactionListenerImpl implements TransactionListener {
|
||||
private AtomicInteger transactionIndex = new AtomicInteger(0);
|
||||
|
||||
private ConcurrentHashMap<String, Integer> localTrans = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
|
||||
return LocalTransactionState.COMMIT_MESSAGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalTransactionState checkLocalTransaction(MessageExt msg) {
|
||||
return LocalTransactionState.COMMIT_MESSAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,9 @@ rocketmq:
|
||||
# configure multiple namesrv addresses to manage multiple different clusters
|
||||
namesrvAddrs:
|
||||
- 127.0.0.1:9876
|
||||
- 127.0.0.2:9876
|
||||
# - 127.0.0.2:9876
|
||||
# - 10.151.47.32:9876;10.151.47.33:9876;10.151.47.34:9876
|
||||
# - 10.151.47.30:9876
|
||||
# if you use rocketmq version < 3.5.8, rocketmq.config.isVIPChannel should be false.default true
|
||||
isVIPChannel:
|
||||
# timeout for mqadminExt, default 5000ms
|
||||
@@ -58,8 +60,8 @@ rocketmq:
|
||||
loginRequired: false
|
||||
useTLS: false
|
||||
# set the accessKey and secretKey if you used acl
|
||||
accessKey: # if version > 4.4.0
|
||||
secretKey: # if version > 4.4.0
|
||||
# accessKey: rocketmq2
|
||||
# secretKey: 12345678
|
||||
|
||||
threadpool:
|
||||
config:
|
||||
|
||||
@@ -15,10 +15,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
app.controller('AppCtrl', ['$scope','$window','$translate','$http','Notification', function ($scope,$window,$translate, $http, Notification) {
|
||||
$scope.rmqVersion = localStorage.getItem("isV5") === "true" ? true : false;
|
||||
|
||||
$scope.changeTranslate = function(langKey){
|
||||
$translate.use(langKey);
|
||||
}
|
||||
|
||||
$scope.changeRMQVersion = function (version) {
|
||||
$scope.rmqVersion = version === 5;
|
||||
localStorage.setItem("isV5", $scope.rmqVersion);
|
||||
}
|
||||
|
||||
$scope.logout = function(){
|
||||
$http({
|
||||
method: "POST",
|
||||
|
||||
@@ -54,9 +54,12 @@ var en = {
|
||||
"RESET_CUS_OFFSET": "Reset Consumer Offset",
|
||||
"DELETE": "Delete",
|
||||
"CHANGE_LANG": "ChangeLanguage",
|
||||
"CHANGE_VERSION": "ChangeVersion",
|
||||
"BROKER": "Broker",
|
||||
"NORMAL": "NORMAL",
|
||||
"RETRY": "RETRY",
|
||||
"FIFO": "FIFO",
|
||||
"TRANSACTION": "TRANSACTION",
|
||||
"DLQ": "DLQ",
|
||||
"QUANTITY":"Quantity",
|
||||
"TYPE":"Type",
|
||||
@@ -123,5 +126,11 @@ var en = {
|
||||
"GROUP_PERM":"Group Permission",
|
||||
"SYNCHRONIZE":"Synchronize Data",
|
||||
"SHOW":"Show",
|
||||
"HIDE":"Hide"
|
||||
"HIDE":"Hide",
|
||||
"MESSAGE_TYPE":"messageType",
|
||||
"MESSAGE_TYPE_UNSPECIFIED": "UNSPECIFIED, is NORMAL",
|
||||
"MESSAGE_TYPE_NORMAL": "NORMAL",
|
||||
"MESSAGE_TYPE_FIFO": "FIFO",
|
||||
"MESSAGE_TYPE_DELAY": "DELAY",
|
||||
"MESSAGE_TYPE_TRANSACTION": "TRANSACTION",
|
||||
}
|
||||
|
||||
@@ -55,9 +55,12 @@ var zh = {
|
||||
"SKIP_MESSAGE_ACCUMULATE":"跳过堆积",
|
||||
"DELETE": "删除",
|
||||
"CHANGE_LANG": "更换语言",
|
||||
"CHANGE_VERSION": "更换版本",
|
||||
"BROKER": "Broker",
|
||||
"NORMAL": "普通",
|
||||
"RETRY": "重试",
|
||||
"FIFO": "顺序",
|
||||
"TRANSACTION": "事务",
|
||||
"DLQ": "死信",
|
||||
"QUANTITY":"数量",
|
||||
"TYPE":"类型",
|
||||
@@ -124,5 +127,11 @@ var zh = {
|
||||
"GROUP_PERM":"消费组权限",
|
||||
"SYNCHRONIZE":"同步",
|
||||
"SHOW":"显示",
|
||||
"HIDE":"隐藏"
|
||||
"HIDE":"隐藏",
|
||||
"MESSAGE_TYPE":"消息类型",
|
||||
"MESSAGE_TYPE_UNSPECIFIED": "未指定,为普通消息",
|
||||
"MESSAGE_TYPE_NORMAL": "普通消息",
|
||||
"MESSAGE_TYPE_FIFO": "顺序消息",
|
||||
"MESSAGE_TYPE_DELAY": "定时/延时消息",
|
||||
"MESSAGE_TYPE_TRANSACTION": "事务消息",
|
||||
}
|
||||
@@ -45,24 +45,30 @@ module.controller('topicController', ['$scope', 'ngDialog', '$http', 'Notificati
|
||||
}
|
||||
};
|
||||
$scope.filterNormal = true
|
||||
$scope.filterDelay = false
|
||||
$scope.filterFifo = false
|
||||
$scope.filterTransaction = false
|
||||
$scope.filterRetry = false
|
||||
$scope.filterDLQ = false
|
||||
$scope.filterSystem = false
|
||||
$scope.allTopicList = [];
|
||||
$scope.allTopicNameList = [];
|
||||
$scope.allMessageTypeList = [];
|
||||
$scope.topicShowList = [];
|
||||
$scope.userRole = $window.sessionStorage.getItem("userrole");
|
||||
$scope.writeOperationEnabled = $scope.userRole == null ? true : ($scope.userRole == 1 ? true : false);
|
||||
$scope.writeOperationEnabled = $scope.userRole == null ? true : ($scope.userRole == 1 ? true : false);
|
||||
|
||||
$scope.refreshTopicList = function () {
|
||||
$http({
|
||||
method: "GET",
|
||||
url: "topic/list.query"
|
||||
url: "topic/list.queryTopicType"
|
||||
}).success(function (resp) {
|
||||
if (resp.status == 0) {
|
||||
$scope.allTopicList = resp.data.topicList.sort();
|
||||
console.log($scope.allTopicList);
|
||||
$scope.allTopicNameList = resp.data.topicNameList;
|
||||
$scope.allMessageTypeList = resp.data.messageTypeList;
|
||||
console.log($scope.allTopicNameList);
|
||||
console.log(JSON.stringify(resp));
|
||||
$scope.showTopicList(1, $scope.allTopicList.length);
|
||||
$scope.showTopicList(1, $scope.allTopicNameList.length);
|
||||
|
||||
} else {
|
||||
Notification.error({message: resp.errMsg, delay: 5000});
|
||||
@@ -79,6 +85,15 @@ module.controller('topicController', ['$scope', 'ngDialog', '$http', 'Notificati
|
||||
$scope.$watch('filterNormal', function () {
|
||||
$scope.filterList(1);
|
||||
});
|
||||
$scope.$watch('filterFifo', function () {
|
||||
$scope.filterList(1);
|
||||
});
|
||||
$scope.$watch('filterTransaction', function () {
|
||||
$scope.filterList(1);
|
||||
});
|
||||
$scope.$watch('filterDelay', function () {
|
||||
$scope.filterList(1);
|
||||
});
|
||||
$scope.$watch('filterRetry', function () {
|
||||
$scope.filterList(1);
|
||||
});
|
||||
@@ -92,13 +107,13 @@ module.controller('topicController', ['$scope', 'ngDialog', '$http', 'Notificati
|
||||
var lowExceptStr = $scope.filterStr.toLowerCase();
|
||||
var canShowList = [];
|
||||
|
||||
$scope.allTopicList.forEach(function (element) {
|
||||
if ($scope.filterByType(element)) {
|
||||
if (element.toLowerCase().indexOf(lowExceptStr) != -1) {
|
||||
canShowList.push(element);
|
||||
for (let i = 0; i < $scope.allTopicNameList.length; ++i) {
|
||||
if ($scope.filterByType($scope.allTopicNameList[i], $scope.allMessageTypeList[i])) {
|
||||
if ($scope.allTopicNameList[i].toLowerCase().indexOf(lowExceptStr) != -1) {
|
||||
canShowList.push($scope.allTopicNameList[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
$scope.paginationConf.totalItems = canShowList.length;
|
||||
var perPage = $scope.paginationConf.itemsPerPage;
|
||||
var from = (currentPage - 1) * perPage;
|
||||
@@ -106,7 +121,7 @@ module.controller('topicController', ['$scope', 'ngDialog', '$http', 'Notificati
|
||||
$scope.topicShowList = canShowList.slice(from, to);
|
||||
};
|
||||
|
||||
$scope.filterByType = function (str) {
|
||||
$scope.filterByType = function (str, type) {
|
||||
if ($scope.filterRetry) {
|
||||
if (str.startsWith("%R")) {
|
||||
return true
|
||||
@@ -123,7 +138,22 @@ module.controller('topicController', ['$scope', 'ngDialog', '$http', 'Notificati
|
||||
}
|
||||
}
|
||||
if ($scope.filterNormal) {
|
||||
if (str.startsWith("%") == false) {
|
||||
if (type.includes("NORMAL")) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if ($scope.filterDelay) {
|
||||
if (type.includes("DELAY")) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if ($scope.filterFifo) {
|
||||
if (type.includes("FIFO")) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if ($scope.filterTransaction) {
|
||||
if (type.includes("TRANSACTION")) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -138,10 +168,10 @@ module.controller('topicController', ['$scope', 'ngDialog', '$http', 'Notificati
|
||||
var perPage = $scope.paginationConf.itemsPerPage;
|
||||
var from = (currentPage - 1) * perPage;
|
||||
var to = (from + perPage) > totalItem ? totalItem : from + perPage;
|
||||
console.log($scope.allTopicList);
|
||||
console.log($scope.allTopicNameList);
|
||||
console.log(from)
|
||||
console.log(to)
|
||||
$scope.topicShowList = $scope.allTopicList.slice(from, to);
|
||||
$scope.topicShowList = $scope.allTopicNameList.slice(from, to);
|
||||
$scope.paginationConf.totalItems = totalItem;
|
||||
console.log($scope.topicShowList)
|
||||
console.log($scope.paginationConf.totalItems)
|
||||
@@ -328,8 +358,8 @@ module.controller('topicController', ['$scope', 'ngDialog', '$http', 'Notificati
|
||||
var bIsUpdate = true;
|
||||
if (request == null) {
|
||||
request = [{
|
||||
writeQueueNums: 16,
|
||||
readQueueNums: 16,
|
||||
writeQueueNums: 8,
|
||||
readQueueNums: 8,
|
||||
perm: 6,
|
||||
order: false,
|
||||
topicName: "",
|
||||
@@ -355,6 +385,7 @@ module.controller('topicController', ['$scope', 'ngDialog', '$http', 'Notificati
|
||||
topicRequestList: request,
|
||||
allClusterNameList: Object.keys(resp.data.clusterInfo.clusterAddrTable),
|
||||
allBrokerNameList: Object.keys(resp.data.brokerServer),
|
||||
allMessageTypeList: resp.data.messageTypes,
|
||||
bIsUpdate: bIsUpdate,
|
||||
writeOperationEnabled: $scope.writeOperationEnabled
|
||||
}
|
||||
|
||||
@@ -47,6 +47,14 @@
|
||||
<li><a href="javascript:void(0)" ng-click="changeTranslate('zh')">Simplified Chinese</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="bootstrap-elements.html" data-target="#" class="dropdown-toggle" data-toggle="dropdown">{{'CHANGE_VERSION' | translate}}
|
||||
<b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="javascript:void(0)" ng-click="changeRMQVersion(5)">RocketMQ 5.x</a></li>
|
||||
<li><a href="javascript:void(0)" ng-click="changeRMQVersion(4)">RocketMQ 4.x</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown" ng-show="username != ''">
|
||||
<a href="bootstrap-elements.html" data-target="#" class="dropdown-toggle" data-toggle="dropdown">{{username}}
|
||||
<b class="caret"></b></a>
|
||||
|
||||
@@ -50,7 +50,14 @@
|
||||
<td class="text-center">{{instance.address}}</td>
|
||||
<td class="text-center">{{instance.brokerVersionDesc}}</td>
|
||||
<td class="text-center">{{instance.putTps.split(' ')[0]| number:2}}</td>
|
||||
<td class="text-center">{{instance.getTransferedTps.split(' ')[0]| number:2}}</td>
|
||||
<td class="text-center">
|
||||
<span ng-if="!instance.getTransferedTps || !instance.getTransferedTps.trim()">
|
||||
{{instance.getTransferredTps.split(' ')[0] | number:2}}
|
||||
</span>
|
||||
<span ng-if="instance.getTransferedTps && instance.getTransferedTps.trim()">
|
||||
{{instance.getTransferedTps.split(' ')[0] | number:2}}
|
||||
</span>
|
||||
</td>
|
||||
<td class="text-center">{{instance.msgPutTotalTodayMorning -
|
||||
instance.msgPutTotalYesterdayMorning}}
|
||||
</td>
|
||||
|
||||
@@ -24,6 +24,12 @@
|
||||
</div>
|
||||
<md-checkbox aria-label="Checkbox" ng-model="filterNormal" class="md-primary">{{'NORMAL' | translate}}
|
||||
</md-checkbox>
|
||||
<md-checkbox aria-label="Checkbox" ng-model="filterDelay" class="md-primary" ng-show="rmqVersion">{{'DELAY' | translate}}
|
||||
</md-checkbox>
|
||||
<md-checkbox aria-label="Checkbox" ng-model="filterFifo" class="md-primary" ng-show="rmqVersion">{{'FIFO' | translate}}
|
||||
</md-checkbox>
|
||||
<md-checkbox aria-label="Checkbox" ng-model="filterTransaction" class="md-primary" ng-show="rmqVersion">{{'TRANSACTION' | translate}}
|
||||
</md-checkbox>
|
||||
<md-checkbox aria-label="Checkbox" ng-model="filterRetry" class="md-primary">{{'RETRY' | translate}}
|
||||
</md-checkbox>
|
||||
<md-checkbox aria-label="Checkbox" ng-model="filterDLQ" class="md-primary">{{'DLQ' | translate}}
|
||||
@@ -63,6 +69,7 @@
|
||||
<button class="btn btn-raised btn-sm btn-primary" type="button"
|
||||
ng-click="openUpdateDialog(topic, sysFlag)">topic {{'CONFIG' |translate}}
|
||||
</button>
|
||||
<!-- todo 发送消息,根据消息类型判断-->
|
||||
<button class="btn btn-raised btn-sm btn-primary" type="button"
|
||||
ng-show="{{!sysFlag}}"
|
||||
ng-click="openSendTopicMessageDialog(topic)">{{'SEND_MSG' | translate}}
|
||||
@@ -189,6 +196,18 @@
|
||||
<span class="text-danger" ng-show="addAppForm.topicName.$error.required">{{'TOPIC_NAME'|translate}}不能为空.</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 设置topic 类型 -->
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">{{'MESSAGE_TYPE'|translate}}:</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="mySelectMessageType" chosen ng-disabled="ngDialogData.bIsUpdate"
|
||||
ng-model="item.messageType"
|
||||
ng-options="messageType as value | translate disable when messageType=='UNSPECIFIED' for (messageType , value) in ngDialogData.allMessageTypeList"
|
||||
>
|
||||
<option value=""></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">{{'WRITE_QUEUE_NUMS'|translate}}:</label>
|
||||
<div class="col-sm-10">
|
||||
|
||||
Reference in New Issue
Block a user