为什么要监控?
1.集群可能有节点挂了,需要告警。
2.有大量的积压消息没有被消费,需要告警。
其实说白了,就是两种情况,一种是挂了,一种是执行慢。这个和之前讲的job监控也是一样的,一种是job挂了,一种是job单次执行慢即超时。
监控指标
1.集群是否有节点挂掉?
2.未消费的积压消息数量
如何比较?
即如何读真实数据,然后和阈值比较?
是否挂了?
先从rocketmq官方工具类读真实数据(集群节点信息),然后和阈值比较:
1、如果集群节点数量为0,表示全挂
2、如果集群节点数量比原始数量小,说明至少挂了一组
注:原始数量的值,可以在配置中心配置。
3、如果集群节点数量和原始数量一样,然后再比较主从节点是否有挂掉
1)如果一组主从节点数量不为2,说明主或从已经挂掉
2)根据节点的值是0/1,判断到底是主节点还是从从节点挂了
源码
public void doProcess() {
LogUtil.LOGGER.info("BrokerClusterJob start");
//获取集群信息
Map<String, Object> map = clusterService.list();
ClusterInfo ClusterInfo = (ClusterInfo) map.get("clusterInfo");
//获取集群ip信息
HashMap<String, BrokerData> brokerAddrTable = ClusterInfo.getBrokerAddrTable();
Config config = ConfigService.getAppConfig();
long clusterNum = config.getLongProperty("rocketmq.cluster.num", 2L);
LogUtil.LOGGER.debug("集群监控数据量{}", clusterNum);
//校验集群ip数量
if (MapUtils.isEmpty(brokerAddrTable)) { //如果为空,说明集群所有节点全部都已经挂掉
LogUtil.LOGGER.warn("集群内容为空");
catMonitor.catBuryPoint("rocketBrokerClusterException", "emptyCluster",
new RocketBrokerClusterException("emptyCluster"), "集群已经出现问题");
} else if (brokerAddrTable.size() != clusterNum) { //如果小于集群总数量,说明有一组主从节点已经挂掉
LogUtil.LOGGER.warn("集群数量不为{}", clusterNum);
catMonitor.catBuryPoint("rocketBrokerClusterException", "downCluster",
new RocketBrokerClusterException("downCluster"), "集群中有一组master挂了");
} else { //集群运行正常
//校验一组主从节点的主或从是否挂掉
for (Map.Entry<String, BrokerData> entry : brokerAddrTable.entrySet()) {
HashMap<Long, String> brokerAddrs = entry.getValue().getBrokerAddrs();
String brokerName = entry.getValue().getBrokerName();
if (brokerAddrs.size() != 2) { //如果一组主从节点数量不为2,说明主或从已经挂掉
//校验是主节点还是从节点挂掉
String params = entry.getKey().equals(0) ? "主节点" : "从节点"; //TODO 这里的校验有问题
catMonitor.catBuryPoint("rocketBrokerClusterException", brokerName,
new RocketBrokerClusterException(brokerName), params);
}
}
}
LogUtil.LOGGER.info("BrokerClusterJob end");
}
是否有积压?
基于官方提供的工具类,可以读集群/group/topic维度的积压数据数量。
然后,拿这些实时数据和阈值比较,就知道有没有积压,积压了多少消息。
源码
@Override
public void doProcess() {
LogUtil.LOGGER.info("RocketmqOffsetJob start");
//获取mq的group集合
List<GroupConsumeInfo> list = consumerService.queryGroupList();
//遍历mq的group集合
for(GroupConsumeInfo groupConsumeInfo : list){
//获取group的积压消息数量
long diffTotal = groupConsumeInfo.getDiffTotal();
long defaultValue = configApp.getLongProperty("group.warn.diffvalue",100l);
long warnvalue = configApp.getLongProperty("group.warn.diffvalue."+groupConsumeInfo.getGroup(),defaultValue);
//校验group的积压消息数量是否超过阈值
if(diffTotal > warnvalue){ //如果超过阈值,则告警
long total = 0;
//获取group的topic集合
List<TopicConsumerInfo> topicConsumerInfoList = consumerService.queryConsumeStatsListByGroupName(groupConsumeInfo.getGroup());
StringBuffer sb = new StringBuffer("消息组:").append(groupConsumeInfo.getGroup()).
append("主题积压消息如下:");
//遍历topic集合,累加得到group的积压消息数量
for(TopicConsumerInfo topicConsumerInfo : topicConsumerInfoList){
sb.append("topic ").append(topicConsumerInfo.getTopic().replace("%RETRY%","")).append("积压了")
.append(topicConsumerInfo.getDiffTotal()).append(",");
total = total+topicConsumerInfo.getDiffTotal();
}
sb.append("总共积压了:").append(total);
if(obj == null){
String names = configApp.getProperty(groupNames,"");
obj = JSONObject.parseObject(names);
}
if(MapUtils.isNotEmpty(obj)){
Object groupName = obj.get(groupConsumeInfo.getGroup());
if(groupName != null){
sb.append(",项目名:").append(groupName);
}
}
LogUtil.LOGGER.warn("group:{}偏移量为{}",groupConsumeInfo.getGroup(),diffTotal);
//监控指标数据:1.group积压消息数量 2.每个topic积压消息数量
catMonitor.catBuryPoint("rocketmqDiffException",groupConsumeInfo.getGroup(),new RocketmqDiffException(groupConsumeInfo.getGroup()),sb.toString());
}
}
LogUtil.LOGGER.info("RocketmqOffsetJob end");
}
实现
配置
启动监控类。
package xxx.monitor.config;
import xxx.log.logback.web.LogbackConfigListener;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.tools.admin.DefaultMQAdminExt;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import xxx.monitor.util.LogUtil;
/**
* web配置
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Value("${rocketmq.config.namesrvAddr}")
private String nameSerAddr;
@Value("${rocketmq.config.isVIPChannel}")
private Boolean isVIPChannel;
@Bean
public ServletListenerRegistrationBean<LogbackConfigListener> initLogbackConfigListener() {
ServletListenerRegistrationBean<LogbackConfigListener> result = new ServletListenerRegistrationBean<>();
result.setListener(new LogbackConfigListener());
return result;
}
/**
* 启动mq监控
*
* @return
* @throws MQClientException
*/
@Bean(name = "defaultMQAdminExt")
public DefaultMQAdminExt initMQAdminInstance() throws MQClientException {
DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt();
defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis()));
LogUtil.LOGGER.info("NamesrvAddr=={},nameSerAddr=={},isVIPChannel={}",defaultMQAdminExt.getNamesrvAddr(),nameSerAddr,isVIPChannel);
defaultMQAdminExt.setNamesrvAddr(nameSerAddr);
defaultMQAdminExt.setVipChannelEnabled(isVIPChannel);
defaultMQAdminExt.start(); //启动mq监控
return defaultMQAdminExt;
}
/**
* 启动mq监控
*
* @return
* @throws MQClientException
*/
@Bean(name = "defaultMQAdminExt2")
public DefaultMQAdminExt initMQAdminInstance2() throws MQClientException {
DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt();
defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis()));
LogUtil.LOGGER.info("NamesrvAddr=={},nameSerAddr=={},isVIPChannel={}",defaultMQAdminExt.getNamesrvAddr(),nameSerAddr,isVIPChannel);
defaultMQAdminExt.setNamesrvAddr("xxx");
defaultMQAdminExt.setVipChannelEnabled(isVIPChannel);
defaultMQAdminExt.start(); //启动mq监控
return defaultMQAdminExt;
}
}
启动job
轮询,比如一分钟读取异常集群的运行时数据。
主要有2个job,即每个监控指标,都搞个job。
/**
* 监控集群节点是否有挂掉
*/
@ElasticJobConf(cron = "0 0/1 * * * ?", name = "BrokerClusterJob", jobParameter = "5", description = "监控rocketmq broker状态", overwrite = true)
public class BrokerClusterJob extends AbstractJob implements SimpleJob {
@Autowired
@Qualifier("clusterServiceImpl")
private ClusterService clusterService; //注入service类
/**
* 监控积压消息数量
*/
@ElasticJobConf(cron = "0 0/1 * * * ?", name = "RocketmqOffsetJob", jobParameter = "5", description = "监控rocketmq消息偏移量", overwrite = true)
public class RocketmqOffsetJob extends AbstractJob implements SimpleJob, InitializingBean {
private final String groupNames = "rocket.group.name";
private JSONObject obj;
@Autowired
@Qualifier("consumerServiceImpl")
private ConsumerService consumerService;
service类
通过调用官方自带的监控类读取运行时数据。
/**
* 获取集群信息
*/
@Service("clusterServiceImpl")
public class ClusterServiceImpl implements ClusterService {
private Logger logger = LoggerFactory.getLogger(ClusterServiceImpl.class);
@Resource
private MQAdminExtImpl mqAdminExtImpl; //主要是把官方自带的工具类注入进来,然后通过工具类来访问运行时数据
官方自带监控工具类
可以复制到自己的项目。
/*
* 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 xxx.monitor.service.client;
import com.google.common.base.Throwables;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.apache.rocketmq.client.QueryResult;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.impl.MQAdminImpl;
import org.apache.rocketmq.common.TopicConfig;
import org.apache.rocketmq.common.admin.ConsumeStats;
import org.apache.rocketmq.common.admin.RollbackStats;
import org.apache.rocketmq.common.admin.TopicStatsTable;
import org.apache.rocketmq.common.message.MessageClientIDSetter;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.protocol.RequestCode;
import org.apache.rocketmq.common.protocol.ResponseCode;
import org.apache.rocketmq.common.protocol.body.BrokerStatsData;
import org.apache.rocketmq.common.protocol.body.ClusterInfo;
import org.apache.rocketmq.common.protocol.body.ConsumeMessageDirectlyResult;
import org.apache.rocketmq.common.protocol.body.ConsumeStatsList;
import org.apache.rocketmq.common.protocol.body.ConsumerConnection;
import org.apache.rocketmq.common.protocol.body.ConsumerRunningInfo;
import org.apache.rocketmq.common.protocol.body.GroupList;
import org.apache.rocketmq.common.protocol.body.KVTable;
import org.apache.rocketmq.common.protocol.body.ProducerConnection;
import org.apache.rocketmq.common.protocol.body.QueueTimeSpan;
import org.apache.rocketmq.common.protocol.body.SubscriptionGroupWrapper;
import org.apache.rocketmq.common.protocol.body.TopicConfigSerializeWrapper;
import org.apache.rocketmq.common.protocol.body.TopicList;
import org.apache.rocketmq.common.protocol.route.TopicRouteData;
import org.apache.rocketmq.common.subscription.SubscriptionGroupConfig;
import org.apache.rocketmq.remoting.RemotingClient;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
import org.apache.rocketmq.remoting.exception.RemotingConnectException;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.rocketmq.remoting.exception.RemotingSendRequestException;
import org.apache.rocketmq.remoting.exception.RemotingTimeoutException;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
import org.apache.rocketmq.tools.admin.DefaultMQAdminExt;
import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.apache.rocketmq.tools.admin.api.MessageTrack;
import org.joor.Reflect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import xxx.monitor.util.JsonUtil;
import xxx.monitor.util.LogUtil;
import static org.apache.rocketmq.remoting.protocol.RemotingSerializable.decode;
/**
* 查询监控数据
*/
@Service
public class MQAdminExtImpl implements MQAdminExt {
private Logger logger = LoggerFactory.getLogger(MQAdminExtImpl.class);
@Autowired
@Qualifier("defaultMQAdminExt")
private DefaultMQAdminExt defaultMQAdminExt;
@Override
public void updateBrokerConfig(String brokerAddr, Properties properties)
throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException,
UnsupportedEncodingException, InterruptedException, MQBrokerException {
defaultMQAdminExt.updateBrokerConfig(brokerAddr, properties);
}
@Override
public void createAndUpdateTopicConfig(String addr, TopicConfig config)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
defaultMQAdminExt.createAndUpdateTopicConfig(addr, config);
}
@Override
public void createAndUpdateSubscriptionGroupConfig(String addr, SubscriptionGroupConfig config)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
defaultMQAdminExt.createAndUpdateSubscriptionGroupConfig(addr, config);
}
@Override
public SubscriptionGroupConfig examineSubscriptionGroupConfig(String addr, String group) {
RemotingClient remotingClient = MQAdminInstance.threadLocalRemotingClient();
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.GET_ALL_SUBSCRIPTIONGROUP_CONFIG, null);
RemotingCommand response = null;
try {
response = remotingClient.invokeSync(addr, request, 3000);
}
catch (Exception err) {
throw Throwables.propagate(err);
}
assert response != null;
switch (response.getCode()) {
case ResponseCode.SUCCESS: {
SubscriptionGroupWrapper subscriptionGroupWrapper = decode(response.getBody(), SubscriptionGroupWrapper.class);
return subscriptionGroupWrapper.getSubscriptionGroupTable().get(group);
}
default:
throw Throwables.propagate(new MQBrokerException(response.getCode(), response.getRemark()));
}
}
@Override
public TopicConfig examineTopicConfig(String addr, String topic) {
RemotingClient remotingClient = MQAdminInstance.threadLocalRemotingClient();
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.GET_ALL_TOPIC_CONFIG, null);
RemotingCommand response = null;
try {
response = remotingClient.invokeSync(addr, request, 3000);
}
catch (Exception err) {
throw Throwables.propagate(err);
}
switch (response.getCode()) {
case ResponseCode.SUCCESS: {
TopicConfigSerializeWrapper topicConfigSerializeWrapper = decode(response.getBody(), TopicConfigSerializeWrapper.class);
return topicConfigSerializeWrapper.getTopicConfigTable().get(topic);
}
default:
throw Throwables.propagate(new MQBrokerException(response.getCode(), response.getRemark()));
}
}
@Override
public TopicStatsTable examineTopicStats(String topic)
throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return defaultMQAdminExt.examineTopicStats(topic);
}
@Override
public TopicList fetchAllTopicList() throws RemotingException, MQClientException, InterruptedException {
TopicList topicList = MQAdminInstance.threadLocalMQAdminExt().fetchAllTopicList();
logger.debug("op=look={}", JsonUtil.obj2String(topicList.getTopicList()));
return topicList;
}
@Override
public KVTable fetchBrokerRuntimeStats(String brokerAddr)
throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException,
InterruptedException, MQBrokerException {
return defaultMQAdminExt.fetchBrokerRuntimeStats(brokerAddr);
}
@Override
public ConsumeStats examineConsumeStats(String consumerGroup)
throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return defaultMQAdminExt.examineConsumeStats(consumerGroup);
}
@Override
public ConsumeStats examineConsumeStats(String consumerGroup, String topic)
throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return defaultMQAdminExt.examineConsumeStats(consumerGroup, topic);
}
@Override
public ClusterInfo examineBrokerClusterInfo()
throws InterruptedException, MQBrokerException, RemotingTimeoutException, RemotingSendRequestException,
RemotingConnectException {
return defaultMQAdminExt.examineBrokerClusterInfo();
}
@Override
public TopicRouteData examineTopicRouteInfo(String topic)
throws RemotingException, MQClientException, InterruptedException {
return defaultMQAdminExt.examineTopicRouteInfo(topic);
}
@Override
public ConsumerConnection examineConsumerConnectionInfo(String consumerGroup)
throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException,
InterruptedException, MQBrokerException, RemotingException, MQClientException {
return defaultMQAdminExt.examineConsumerConnectionInfo(consumerGroup);
}
@Override
public ProducerConnection examineProducerConnectionInfo(String producerGroup, String topic)
throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return defaultMQAdminExt.examineProducerConnectionInfo(producerGroup, topic);
}
@Override
public List<String> getNameServerAddressList() {
return defaultMQAdminExt.getNameServerAddressList();
}
@Override
public int wipeWritePermOfBroker(String namesrvAddr, String brokerName)
throws RemotingCommandException, RemotingConnectException, RemotingSendRequestException,
RemotingTimeoutException, InterruptedException, MQClientException {
return defaultMQAdminExt.wipeWritePermOfBroker(namesrvAddr, brokerName);
}
@Override
public void putKVConfig(String namespace, String key, String value) {
defaultMQAdminExt.putKVConfig(namespace, key, value);
}
@Override
public String getKVConfig(String namespace, String key)
throws RemotingException, MQClientException, InterruptedException {
return defaultMQAdminExt.getKVConfig(namespace, key);
}
@Override
public KVTable getKVListByNamespace(String namespace)
throws RemotingException, MQClientException, InterruptedException {
return defaultMQAdminExt.getKVListByNamespace(namespace);
}
@Override
public void deleteTopicInBroker(Set<String> addrs, String topic)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
logger.info("addrs={} topic={}", JsonUtil.obj2String(addrs), topic);
defaultMQAdminExt.deleteTopicInBroker(addrs, topic);
}
@Override
public void deleteTopicInNameServer(Set<String> addrs, String topic)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
defaultMQAdminExt.deleteTopicInNameServer(addrs, topic);
}
@Override
public void deleteSubscriptionGroup(String addr, String groupName)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
defaultMQAdminExt.deleteSubscriptionGroup(addr, groupName);
}
@Override
public void createAndUpdateKvConfig(String namespace, String key, String value)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
defaultMQAdminExt.createAndUpdateKvConfig(namespace, key, value);
}
@Override
public void deleteKvConfig(String namespace, String key)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
defaultMQAdminExt.deleteKvConfig(namespace, key);
}
@Override
public List<RollbackStats> resetOffsetByTimestampOld(String consumerGroup, String topic, long timestamp,
boolean force) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
return defaultMQAdminExt.resetOffsetByTimestampOld(consumerGroup, topic, timestamp, force);
}
@Override
public Map<MessageQueue, Long> resetOffsetByTimestamp(String topic, String group, long timestamp,
boolean isForce) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
return defaultMQAdminExt.resetOffsetByTimestamp(topic, group, timestamp, isForce);
}
@Override
public void resetOffsetNew(String consumerGroup, String topic, long timestamp)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
defaultMQAdminExt.resetOffsetNew(consumerGroup, topic, timestamp);
}
@Override
public Map<String, Map<MessageQueue, Long>> getConsumeStatus(String topic, String group,
String clientAddr) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
return defaultMQAdminExt.getConsumeStatus(topic, group, clientAddr);
}
@Override
public void createOrUpdateOrderConf(String key, String value, boolean isCluster)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
defaultMQAdminExt.createOrUpdateOrderConf(key, value, isCluster);
}
@Override
public GroupList queryTopicConsumeByWho(String topic)
throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException,
InterruptedException, MQBrokerException, RemotingException, MQClientException {
return defaultMQAdminExt.queryTopicConsumeByWho(topic);
}
@Override
public boolean cleanExpiredConsumerQueue(String cluster)
throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException,
InterruptedException {
return defaultMQAdminExt.cleanExpiredConsumerQueue(cluster);
}
@Override
public boolean cleanExpiredConsumerQueueByAddr(String addr)
throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException,
InterruptedException {
return defaultMQAdminExt.cleanExpiredConsumerQueueByAddr(addr);
}
@Override
public ConsumerRunningInfo getConsumerRunningInfo(String consumerGroup, String clientId, boolean jstack)
throws RemotingException, MQClientException, InterruptedException {
return defaultMQAdminExt.getConsumerRunningInfo(consumerGroup, clientId, jstack);
}
@Override
public ConsumeMessageDirectlyResult consumeMessageDirectly(String consumerGroup, String clientId,
String msgId) throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return defaultMQAdminExt.consumeMessageDirectly(consumerGroup, clientId, msgId);
}
@Override
public List<MessageTrack> messageTrackDetail(MessageExt msg)
throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return defaultMQAdminExt.messageTrackDetail(msg);
}
@Override
public void cloneGroupOffset(String srcGroup, String destGroup, String topic, boolean isOffline)
throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
defaultMQAdminExt.cloneGroupOffset(srcGroup, destGroup, topic, isOffline);
}
@Override
public void createTopic(String key, String newTopic, int queueNum) throws MQClientException {
defaultMQAdminExt.createTopic(key, newTopic, queueNum);
}
@Override
public void createTopic(String key, String newTopic, int queueNum, int topicSysFlag)
throws MQClientException {
defaultMQAdminExt.createTopic(key, newTopic, queueNum, topicSysFlag);
}
@Override
public long searchOffset(MessageQueue mq, long timestamp) throws MQClientException {
return defaultMQAdminExt.searchOffset(mq, timestamp);
}
@Override
public long maxOffset(MessageQueue mq) throws MQClientException {
return defaultMQAdminExt.maxOffset(mq);
}
@Override
public long minOffset(MessageQueue mq) throws MQClientException {
return defaultMQAdminExt.minOffset(mq);
}
@Override
public long earliestMsgStoreTime(MessageQueue mq) throws MQClientException {
return defaultMQAdminExt.earliestMsgStoreTime(mq);
}
@Override
public MessageExt viewMessage(String msgId)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
return defaultMQAdminExt.viewMessage(msgId);
}
@Override
public QueryResult queryMessage(String topic, String key, int maxNum, long begin, long end)
throws MQClientException, InterruptedException {
return defaultMQAdminExt.queryMessage(topic, key, maxNum, begin, end);
}
/**
* @deprecated thisMethod is deprecated.use org.apache.rocketmq.console.aspect.admin.MQAdminAspect instead of this
* @throws MQClientException
*/
@Override
@Deprecated
public void start() throws MQClientException {
throw new IllegalStateException("thisMethod is deprecated.use org.apache.rocketmq.console.aspect.admin.MQAdminAspect instead of this");
}
/**
* @deprecated thisMethod is deprecated.use org.apache.rocketmq.console.aspect.admin.MQAdminAspect instead of this
*/
@Override
@Deprecated
public void shutdown() {
throw new IllegalStateException("thisMethod is deprecated.use org.apache.rocketmq.console.aspect.admin.MQAdminAspect instead of this");
}
// below is 3.2.6->3.5.8 updated
@Override
public List<QueueTimeSpan> queryConsumeTimeSpan(String topic,
String group) throws InterruptedException, MQBrokerException, RemotingException, MQClientException {
return defaultMQAdminExt.queryConsumeTimeSpan(topic, group);
}
//MessageClientIDSetter.getNearlyTimeFromID has bug,so we subtract half a day
//next version we will remove it
//https://issues.apache.org/jira/browse/ROCKETMQ-111
//https://github.com/apache/incubator-rocketmq/pull/69
@Override
public MessageExt viewMessage(String topic,
String msgId) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
logger.info("MessageClientIDSetter.getNearlyTimeFromID(msgId)={} msgId={}", MessageClientIDSetter.getNearlyTimeFromID(msgId), msgId);
try {
return viewMessage(msgId);
}
catch (Exception e) {
LogUtil.LOGGER.error("viewMessage error",e);
}
MQAdminImpl mqAdminImpl = MQAdminInstance.threadLocalMqClientInstance().getMQAdminImpl();
QueryResult qr = Reflect.on(mqAdminImpl).call("queryMessage", topic, msgId, 32,
MessageClientIDSetter.getNearlyTimeFromID(msgId).getTime() - 1000 * 60 * 60 * 13L, Long.MAX_VALUE, true).get();
if (qr != null && qr.getMessageList() != null && qr.getMessageList().size() > 0) {
return qr.getMessageList().get(0);
}
else {
return null;
}
}
@Override
public ConsumeMessageDirectlyResult consumeMessageDirectly(String consumerGroup, String clientId, String topic,
String msgId) throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return defaultMQAdminExt.consumeMessageDirectly(consumerGroup, clientId, topic, msgId);
}
@Override
public Properties getBrokerConfig(
String brokerAddr) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, UnsupportedEncodingException, InterruptedException, MQBrokerException {
return defaultMQAdminExt.getBrokerConfig(brokerAddr);
}
@Override
public TopicList fetchTopicsByCLuster(
String clusterName) throws RemotingException, MQClientException, InterruptedException {
return defaultMQAdminExt.fetchTopicsByCLuster(clusterName);
}
@Override
public boolean cleanUnusedTopic(
String cluster) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, InterruptedException {
return defaultMQAdminExt.cleanUnusedTopic(cluster);
}
@Override
public boolean cleanUnusedTopicByAddr(
String addr) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, InterruptedException {
return defaultMQAdminExt.cleanUnusedTopicByAddr(addr);
}
@Override
public BrokerStatsData viewBrokerStatsData(String brokerAddr, String statsName,
String statsKey) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, InterruptedException {
return defaultMQAdminExt.viewBrokerStatsData(brokerAddr, statsName, statsKey);
}
@Override
public Set<String> getClusterList(
String topic) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, InterruptedException {
return defaultMQAdminExt.getClusterList(topic);
}
@Override
public ConsumeStatsList fetchConsumeStatsInBroker(String brokerAddr, boolean isOrder,
long timeoutMillis) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, InterruptedException {
return defaultMQAdminExt.fetchConsumeStatsInBroker(brokerAddr, isOrder, timeoutMillis);
}
@Override
public Set<String> getTopicClusterList(
String topic) throws InterruptedException, MQBrokerException, MQClientException, RemotingException {
return defaultMQAdminExt.getTopicClusterList(topic);
}
@Override
public SubscriptionGroupWrapper getAllSubscriptionGroup(String brokerAddr,
long timeoutMillis) throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException, MQBrokerException {
return defaultMQAdminExt.getAllSubscriptionGroup(brokerAddr, timeoutMillis);
}
@Override
public TopicConfigSerializeWrapper getAllTopicGroup(String brokerAddr,
long timeoutMillis) throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException, MQBrokerException {
return defaultMQAdminExt.getAllTopicGroup(brokerAddr, timeoutMillis);
}
@Override
public void updateConsumeOffset(String brokerAddr, String consumeGroup, MessageQueue mq,
long offset) throws RemotingException, InterruptedException, MQBrokerException {
defaultMQAdminExt.updateConsumeOffset(brokerAddr, consumeGroup, mq, offset);
}
// 4.0.0 added
@Override
public void updateNameServerConfig(Properties properties,
List<String> list) throws InterruptedException, RemotingConnectException, UnsupportedEncodingException, RemotingSendRequestException, RemotingTimeoutException, MQClientException, MQBrokerException {
}
@Override public Map<String, Properties> getNameServerConfig(
List<String> list) throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException, MQClientException, UnsupportedEncodingException {
return null;
}
}
多套集群监控
实现
核心点是上面实现步骤里的每一步,都再来一套。 这里有个关键的问题是,有两套数据源,但是如何区分bean不同的实例?核心是通过bean的名字来区分。
如何区分bean的多个实例?
bean有多个实例
一、通过@bean注解创建bean
@bean注解带上名字表示,
1.@bean注解是创建bean
2.带上名字是可以用来区分不同的实例
@Bean(name = "defaultMQAdminExt")
@Bean(name = "defaultMQAdminExt2")
二、注入bean
@Autowired //注入数据
@Qualifier("defaultMQAdminExt") //@Qualifier注解的作用是指定bean名字,即使用bean的哪个实例
private DefaultMQAdminExt defaultMQAdminExt;
bean接口有多个实现类
一、通过@Service创建bean
同一个接口的实现类1
/**
* 获取集群信息
*/
@Service("clusterServiceImpl")
public class ClusterServiceImpl implements ClusterService {
同一个接口的实现类2
/**
* 获取集群信息
*/
@Service("clusterServiceImpl2") //指定bean名字
public class ClusterServiceImpl2 implements ClusterService {
二、注入bean
如果是单例,类的属性名字clusterService默认就是bean的名字,而且不需要指定名字。但是,如果是多例,就必须要指定名字,才能指定用的是哪个实例,否则会报错。
@Autowired
@Qualifier("clusterServiceImpl")
private ClusterService clusterService;
@Autowired
@Qualifier("clusterServiceImpl2")
private ClusterService clusterService;