├── screenshot
├── menu.png
├── cluster.png
├── cusumer.png
├── cusumer1.png
├── cusumer2.png
└── topiclist.png
├── src
└── main
│ ├── resources
│ ├── app.properties
│ ├── logback.xml
│ └── spring
│ │ ├── context.xml
│ │ └── mvc.xml
│ ├── webapp
│ ├── META-INF
│ │ └── context.xml
│ ├── index.jsp
│ ├── css
│ │ └── style.css
│ └── WEB-INF
│ │ ├── web.xml
│ │ └── jsp
│ │ ├── topiclist.jsp
│ │ ├── topicstats.jsp
│ │ ├── clusterlist.jsp
│ │ └── consumerprogress.jsp
│ └── java
│ └── com
│ └── alibaba
│ └── rocketmq
│ └── web
│ ├── util
│ └── LoggerUtil.java
│ └── rocketmq
│ └── web
│ ├── bo
│ ├── TopicStatsBo.java
│ ├── TotalConsumerProgress.java
│ ├── ClusterInfoBo.java
│ └── SingleConsumerProgress.java
│ ├── controller
│ └── RocketMQController.java
│ └── service
│ └── RocketMQService.java
├── README.md
├── nb-configuration.xml
└── pom.xml
/screenshot/menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wang55www/rocketmq-web/HEAD/screenshot/menu.png
--------------------------------------------------------------------------------
/screenshot/cluster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wang55www/rocketmq-web/HEAD/screenshot/cluster.png
--------------------------------------------------------------------------------
/screenshot/cusumer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wang55www/rocketmq-web/HEAD/screenshot/cusumer.png
--------------------------------------------------------------------------------
/screenshot/cusumer1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wang55www/rocketmq-web/HEAD/screenshot/cusumer1.png
--------------------------------------------------------------------------------
/screenshot/cusumer2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wang55www/rocketmq-web/HEAD/screenshot/cusumer2.png
--------------------------------------------------------------------------------
/screenshot/topiclist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wang55www/rocketmq-web/HEAD/screenshot/topiclist.png
--------------------------------------------------------------------------------
/src/main/resources/app.properties:
--------------------------------------------------------------------------------
1 | #=== rocket mq config ===
2 | rocketmq.namesrv.addr=192.168.152.103:9876;192.168.152.104:9876
3 |
--------------------------------------------------------------------------------
/src/main/webapp/META-INF/context.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | rocketmq-web
2 | =============
3 | 项目说明:rocketmq web版控制台
4 |
5 | namesrv设置方法:
6 | 一下几种方法按照优先级从高到低排序
7 | * 启动时设置 jvm 的启动参数 rocketmq.namesrv.addr
8 | * 设置系统的环境变量 NAMESRV_ADDR
9 | * 设置项目中 src/main/resources/app.properties 中 rocketmq.namesrv.addr属性
10 |
--------------------------------------------------------------------------------
/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 | [%d %-5level %thread %class{0}:%line] %msg%n
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 | <%@page contentType="text/html" pageEncoding="UTF-8"%>
2 |
4 |
5 |
6 |
7 |
8 | RocketMQ 监控
9 |
10 |
11 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/main/webapp/css/style.css:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2014 wangxiangnan.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | /*
17 | Created on : 2014-9-11, 17:51:23
18 | Author : wangxiangnan
19 | */
20 |
21 | body{
22 | font-size: 14px;
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/src/main/resources/spring/context.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/main/java/com/alibaba/rocketmq/web/util/LoggerUtil.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 wangxiangnan.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alibaba.rocketmq.web.util;
18 |
19 | import org.slf4j.Logger;
20 | import org.slf4j.LoggerFactory;
21 |
22 | /**
23 | *
24 | * @author xiangnan.wang@ipinyou.com
25 | */
26 | public class LoggerUtil {
27 |
28 | private static Logger logger=LoggerFactory.getLogger("rocket-web");
29 |
30 | public static Logger getLogger(){
31 | return logger;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | rocketmq-web
7 |
8 |
9 | encoding
10 | org.springframework.web.filter.CharacterEncodingFilter
11 |
12 | encoding
13 | utf-8
14 |
15 |
16 |
17 |
18 | encoding
19 | Spring MVC Dispatcher Servlet
20 |
21 |
22 |
23 | Spring MVC Dispatcher Servlet
24 | org.springframework.web.servlet.DispatcherServlet
25 |
26 | contextConfigLocation
27 | classpath*:spring/*.xml
28 |
29 | 1
30 |
31 |
32 |
33 | Spring MVC Dispatcher Servlet
34 | /
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/jsp/topiclist.jsp:
--------------------------------------------------------------------------------
1 | <%--
2 | Document : clusterlist
3 | Created on : 2014-9-10, 17:12:03
4 | Author : wangxiangnan
5 | --%>
6 |
7 | <%@page contentType="text/html" pageEncoding="UTF-8"%>
8 | <%@page isELIgnored="false" %>
9 | <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
10 | <%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
11 |
12 |
13 |
14 |
15 |
16 | topicList
17 |
18 |
19 |
20 | topic列表
21 |
22 |
23 |
24 | | topic |
25 |
26 |
27 |
28 |
29 |
30 | | ${topic} |
31 |
32 |
33 |
34 |
35 |
36 | 返回
37 |
38 |
39 |
--------------------------------------------------------------------------------
/nb-configuration.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
16 | 1.6-web
17 | Tomcat
18 | apache20
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/main/resources/spring/mvc.xml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/jsp/topicstats.jsp:
--------------------------------------------------------------------------------
1 | <%--
2 | Document : clusterlist
3 | Created on : 2014-9-10, 17:12:03
4 | Author : wangxiangnan
5 | --%>
6 |
7 | <%@page contentType="text/html" pageEncoding="UTF-8"%>
8 | <%@page isELIgnored="false" %>
9 | <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
10 | <%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
11 |
12 |
13 |
14 |
15 |
16 | topicStats
17 |
18 |
19 |
20 | topic状态信息
21 |
22 |
23 |
24 | | broker名称 |
25 | 队列ID |
26 | 最小偏移量 |
27 | 最大偏移量 |
28 | 最近更新时间 |
29 |
30 |
31 |
32 |
33 |
34 | | ${ts.brokerName} |
35 | ${ts.qid} |
36 | ${ts.minOffset} |
37 | ${ts.maxOffset} |
38 | |
39 |
40 |
41 |
42 |
43 |
44 | 返回
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/jsp/clusterlist.jsp:
--------------------------------------------------------------------------------
1 | <%--
2 | Document : clusterlist
3 | Created on : 2014-9-10, 17:12:03
4 | Author : wangxiangnan
5 | --%>
6 |
7 | <%@page contentType="text/html" pageEncoding="UTF-8"%>
8 | <%@page isELIgnored="false" %>
9 | <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
10 | <%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
11 |
12 |
13 |
14 |
15 |
16 | cluster list
17 |
18 |
19 |
20 | 集群列表
21 |
22 |
23 |
24 | | 集群名称 |
25 | broker名称 |
26 | brokerId |
27 | ip |
28 | 版本 |
29 | 输入TPS |
30 | 输出TPS |
31 |
32 |
33 |
34 |
35 |
36 | | ${cib.clusterName} |
37 | ${cib.brokerName} |
38 | ${cib.bid} |
39 | ${cib.addr} |
40 | ${cib.version} |
41 | |
42 | |
43 |
44 |
45 |
46 |
47 |
48 | 返回
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/main/java/com/alibaba/rocketmq/web/rocketmq/web/bo/TopicStatsBo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 wangxiangnan.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alibaba.rocketmq.web.rocketmq.web.bo;
18 |
19 | import java.util.Date;
20 |
21 | /**
22 | *
23 | * @author xiangnan.wang@ipinyou.com
24 | */
25 | public class TopicStatsBo {
26 |
27 | private String brokerName;
28 |
29 | private int qid;
30 |
31 | private long minOffset;
32 |
33 | private long maxOffset;
34 |
35 | private Date lastUpdate;
36 |
37 | public String getBrokerName() {
38 | return brokerName;
39 | }
40 |
41 | public void setBrokerName(String brokerName) {
42 | this.brokerName = brokerName;
43 | }
44 |
45 | public int getQid() {
46 | return qid;
47 | }
48 |
49 | public void setQid(int qid) {
50 | this.qid = qid;
51 | }
52 |
53 | public long getMinOffset() {
54 | return minOffset;
55 | }
56 |
57 | public void setMinOffset(long minOffset) {
58 | this.minOffset = minOffset;
59 | }
60 |
61 | public long getMaxOffset() {
62 | return maxOffset;
63 | }
64 |
65 | public void setMaxOffset(long maxOffset) {
66 | this.maxOffset = maxOffset;
67 | }
68 |
69 | public Date getLastUpdate() {
70 | return lastUpdate;
71 | }
72 |
73 | public void setLastUpdate(Date lastUpdate) {
74 | this.lastUpdate = lastUpdate;
75 | }
76 |
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/com/alibaba/rocketmq/web/rocketmq/web/bo/TotalConsumerProgress.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 wangxiangnan.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alibaba.rocketmq.web.rocketmq.web.bo;
18 |
19 | /**
20 | *
21 | * @author xiangnan.wang@ipinyou.com
22 | */
23 | public class TotalConsumerProgress implements Comparable{
24 |
25 | private String group;
26 |
27 | private int count;
28 |
29 | private String version;
30 |
31 | private String type;
32 |
33 | private long tps;
34 |
35 | private long diff;
36 |
37 |
38 | public String getGroup() {
39 | return group;
40 | }
41 |
42 | public void setGroup(String group) {
43 | this.group = group;
44 | }
45 |
46 | public int getCount() {
47 | return count;
48 | }
49 |
50 | public void setCount(int count) {
51 | this.count = count;
52 | }
53 |
54 | public String getVersion() {
55 | return version;
56 | }
57 |
58 | public void setVersion(String version) {
59 | this.version = version;
60 | }
61 |
62 | public String getType() {
63 | return type;
64 | }
65 |
66 | public void setType(String type) {
67 | this.type = type;
68 | }
69 |
70 | public long getTps() {
71 | return tps;
72 | }
73 |
74 | public void setTps(long tps) {
75 | this.tps = tps;
76 | }
77 |
78 | public long getDiff() {
79 | return diff;
80 | }
81 |
82 | public void setDiff(long diff) {
83 | this.diff = diff;
84 | }
85 |
86 | @Override
87 | public int compareTo(TotalConsumerProgress o) {
88 | if (this.count != o.count) {
89 | return o.count - this.count;
90 | }
91 |
92 | return (int) (o.diff - diff);
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/src/main/java/com/alibaba/rocketmq/web/rocketmq/web/bo/ClusterInfoBo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 wangxiangnan.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alibaba.rocketmq.web.rocketmq.web.bo;
18 |
19 | /**
20 | *
21 | * @author xiangnan.wang@ipinyou.com
22 | */
23 | public class ClusterInfoBo {
24 |
25 | private String clusterName;
26 |
27 | private String brokerName;
28 |
29 | private String bid;
30 |
31 | private String addr;
32 |
33 | private String version;
34 |
35 | private double inTps;
36 |
37 | private double outTps;
38 |
39 | public String getClusterName() {
40 | return clusterName;
41 | }
42 |
43 | public void setClusterName(String clusterName) {
44 | this.clusterName = clusterName;
45 | }
46 |
47 | public String getBrokerName() {
48 | return brokerName;
49 | }
50 |
51 | public void setBrokerName(String brokerName) {
52 | this.brokerName = brokerName;
53 | }
54 |
55 | public String getBid() {
56 | return bid;
57 | }
58 |
59 | public void setBid(String bid) {
60 | this.bid = bid;
61 | }
62 |
63 | public String getAddr() {
64 | return addr;
65 | }
66 |
67 | public void setAddr(String addr) {
68 | this.addr = addr;
69 | }
70 |
71 | public String getVersion() {
72 | return version;
73 | }
74 |
75 | public void setVersion(String version) {
76 | this.version = version;
77 | }
78 |
79 | public double getInTps() {
80 | return inTps;
81 | }
82 |
83 | public void setInTps(double inTps) {
84 | this.inTps = inTps;
85 | }
86 |
87 | public double getOutTps() {
88 | return outTps;
89 | }
90 |
91 | public void setOutTps(double outTps) {
92 | this.outTps = outTps;
93 | }
94 |
95 | @Override
96 | public String toString() {
97 | return "ClusterInfoBo{" + "clusterName=" + clusterName + ", brokerName=" + brokerName + ", bid=" + bid + ", addr=" + addr + ", version=" + version + ", inTps=" + inTps + ", outTps=" + outTps + '}';
98 | }
99 |
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/jsp/consumerprogress.jsp:
--------------------------------------------------------------------------------
1 | <%--
2 | Document : clusterlist
3 | Created on : 2014-9-10, 17:12:03
4 | Author : wangxiangnan
5 | --%>
6 |
7 | <%@page contentType="text/html" pageEncoding="UTF-8"%>
8 | <%@page isELIgnored="false" %>
9 | <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
10 | <%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
11 |
12 |
13 |
14 |
15 |
16 | consumerprogress
17 |
18 |
19 |
20 | 消费进度
21 |
22 |
23 |
24 |
25 |
26 | | 消费组名称 |
27 | 客户端连接数 |
28 | 客户端版本 |
29 | 消费类型 |
30 | TPS |
31 | 进度差 |
32 |
33 |
34 |
35 |
36 |
37 | | ${cp.group} |
38 | ${cp.count} |
39 | ${cp.version} |
40 | ${cp.type} |
41 | ${cp.tps} |
42 | ${cp.diff} |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | | topic |
55 | brocker名称 |
56 | 队列ID |
57 | broker偏移量 |
58 | 消费偏移量 |
59 | 进度差 |
60 |
61 |
62 |
63 |
64 |
65 | | ${cd.topic} |
66 | ${cd.brokerName} |
67 | ${cd.mqId} |
68 | ${cd.brokerOffset} |
69 | ${cd.consumerOffset} |
70 | ${cd.diff} |
71 |
72 |
73 |
74 |
75 |
76 |
77 | 返回
78 | 返回
79 |
80 |
81 |
--------------------------------------------------------------------------------
/src/main/java/com/alibaba/rocketmq/web/rocketmq/web/bo/SingleConsumerProgress.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 wangxiangnan.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.alibaba.rocketmq.web.rocketmq.web.bo;
17 |
18 | import java.util.List;
19 |
20 | /**
21 | *
22 | * @author xiangnan.wang@ipinyou.com
23 | */
24 | public class SingleConsumerProgress {
25 |
26 | private long tps;
27 |
28 | private long totalDiff;
29 |
30 | private List cdList;
31 |
32 | public long getTps() {
33 | return tps;
34 | }
35 |
36 | public void setTps(long tps) {
37 | this.tps = tps;
38 | }
39 |
40 | public long getTotalDiff() {
41 | return totalDiff;
42 | }
43 |
44 | public void setTotalDiff(long totalDiff) {
45 | this.totalDiff = totalDiff;
46 | }
47 |
48 | public List getCdList() {
49 | return cdList;
50 | }
51 |
52 | public void setCdList(List cdList) {
53 | this.cdList = cdList;
54 | }
55 |
56 | public static class ConsumerDetail {
57 |
58 | private String topic;
59 |
60 | private String brokerName;
61 |
62 | private int mqId;
63 |
64 | private long brokerOffset;
65 |
66 | private long consumerOffset;
67 |
68 | private long diff;
69 |
70 | public String getTopic() {
71 | return topic;
72 | }
73 |
74 | public void setTopic(String topic) {
75 | this.topic = topic;
76 | }
77 |
78 | public String getBrokerName() {
79 | return brokerName;
80 | }
81 |
82 | public void setBrokerName(String brokerName) {
83 | this.brokerName = brokerName;
84 | }
85 |
86 | public int getMqId() {
87 | return mqId;
88 | }
89 |
90 | public void setMqId(int mqId) {
91 | this.mqId = mqId;
92 | }
93 |
94 | public long getBrokerOffset() {
95 | return brokerOffset;
96 | }
97 |
98 | public void setBrokerOffset(long brokerOffset) {
99 | this.brokerOffset = brokerOffset;
100 | }
101 |
102 | public long getConsumerOffset() {
103 | return consumerOffset;
104 | }
105 |
106 | public void setConsumerOffset(long consumerOffset) {
107 | this.consumerOffset = consumerOffset;
108 | }
109 |
110 | public long getDiff() {
111 | return diff;
112 | }
113 |
114 | public void setDiff(long diff) {
115 | this.diff = diff;
116 | }
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/src/main/java/com/alibaba/rocketmq/web/rocketmq/web/controller/RocketMQController.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 wangxiangnan.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alibaba.rocketmq.web.rocketmq.web.controller;
18 |
19 | import com.alibaba.rocketmq.web.rocketmq.web.bo.ClusterInfoBo;
20 | import com.alibaba.rocketmq.web.rocketmq.web.bo.SingleConsumerProgress;
21 | import com.alibaba.rocketmq.web.rocketmq.web.bo.TopicStatsBo;
22 | import com.alibaba.rocketmq.web.rocketmq.web.bo.TotalConsumerProgress;
23 | import com.alibaba.rocketmq.web.rocketmq.web.service.RocketMQService;
24 | import java.util.Collections;
25 | import java.util.List;
26 | import java.util.Set;
27 | import org.springframework.beans.factory.annotation.Autowired;
28 | import org.springframework.stereotype.Controller;
29 | import org.springframework.web.bind.annotation.PathVariable;
30 | import org.springframework.web.bind.annotation.RequestMapping;
31 | import org.springframework.web.servlet.ModelAndView;
32 |
33 | /**
34 | *
35 | * @author xiangnan.wang@ipinyou.com
36 | */
37 | @Controller
38 | public class RocketMQController {
39 |
40 | @Autowired
41 | private RocketMQService rmqService;
42 |
43 | @RequestMapping("/clusterList")
44 | public ModelAndView getClusterList(){
45 | List cibl=rmqService.getClusterInfo();
46 | ModelAndView mv=new ModelAndView();
47 | mv.setViewName("clusterlist");
48 | mv.addObject("cibl", cibl);
49 | return mv;
50 | }
51 |
52 | @RequestMapping("/consumerProgress/{group}")
53 | public ModelAndView consumerProgress(@PathVariable String group){
54 | ModelAndView mv=new ModelAndView();
55 | SingleConsumerProgress scp=rmqService.consumerProgress(group);
56 | mv.addObject("result", scp);
57 | mv.addObject("all",false);
58 | mv.setViewName("consumerprogress");
59 | return mv;
60 | }
61 |
62 | @RequestMapping("/consumerProgress")
63 | public ModelAndView consumerProgress(){
64 | ModelAndView mv=new ModelAndView();
65 | List tcpList=rmqService.consumerProgress();
66 | Collections.sort(tcpList);
67 | mv.addObject("result", tcpList);
68 | mv.addObject("all",true);
69 | mv.setViewName("consumerprogress");
70 | return mv;
71 | }
72 |
73 | @RequestMapping("topicList")
74 | public ModelAndView topicList(){
75 | ModelAndView mv=new ModelAndView();
76 | Set topicSet=rmqService.getTopics();
77 | mv.addObject("result",topicSet);
78 | mv.setViewName("topiclist");
79 | return mv;
80 | }
81 |
82 | @RequestMapping("topicStats/{topic}")
83 | public ModelAndView topicStats(@PathVariable String topic){
84 | ModelAndView mv=new ModelAndView();
85 | List tsbList=rmqService.getTopicStats(topic);
86 | mv.addObject("result", tsbList);
87 | mv.setViewName("topicstats");
88 | return mv;
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | com.alibaba.rocketmq.web
6 | rocketmq-web
7 | 1.0-SNAPSHOT
8 | war
9 |
10 | rocketmq-web
11 |
12 |
13 | ${project.build.directory}/endorsed
14 | UTF-8
15 | 3.1.8
16 |
17 |
18 |
19 |
20 | org.springframework
21 | spring-webmvc
22 | 3.2.3.RELEASE
23 |
24 |
25 | com.alibaba.rocketmq
26 | rocketmq-tools
27 | ${rocketmq.version}
28 |
29 |
30 | javax.servlet
31 | jstl
32 | 1.2
33 |
34 |
35 | javax
36 | javaee-web-api
37 | 6.0
38 | provided
39 |
40 |
41 |
42 |
43 |
44 |
45 | org.apache.maven.plugins
46 | maven-compiler-plugin
47 | 2.3.2
48 |
49 | 1.6
50 | 1.6
51 |
52 | ${endorsed.dir}
53 |
54 |
55 |
56 |
57 | org.apache.maven.plugins
58 | maven-war-plugin
59 | 2.1.1
60 |
61 | false
62 |
63 |
64 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/src/main/java/com/alibaba/rocketmq/web/rocketmq/web/service/RocketMQService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 wangxiangnan.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.alibaba.rocketmq.web.rocketmq.web.service;
18 |
19 | import com.alibaba.rocketmq.common.MQVersion;
20 | import com.alibaba.rocketmq.common.MixAll;
21 | import com.alibaba.rocketmq.common.admin.ConsumeStats;
22 | import com.alibaba.rocketmq.common.admin.OffsetWrapper;
23 | import com.alibaba.rocketmq.common.admin.TopicOffset;
24 | import com.alibaba.rocketmq.common.admin.TopicStatsTable;
25 | import com.alibaba.rocketmq.common.message.MessageQueue;
26 | import com.alibaba.rocketmq.common.protocol.body.ClusterInfo;
27 | import com.alibaba.rocketmq.common.protocol.body.ConsumerConnection;
28 | import com.alibaba.rocketmq.common.protocol.body.TopicList;
29 | import com.alibaba.rocketmq.common.protocol.heartbeat.ConsumeType;
30 | import com.alibaba.rocketmq.common.protocol.route.BrokerData;
31 | import com.alibaba.rocketmq.tools.admin.DefaultMQAdminExt;
32 | import com.alibaba.rocketmq.web.rocketmq.web.bo.ClusterInfoBo;
33 | import com.alibaba.rocketmq.web.rocketmq.web.bo.SingleConsumerProgress;
34 | import com.alibaba.rocketmq.web.rocketmq.web.bo.TopicStatsBo;
35 | import com.alibaba.rocketmq.web.rocketmq.web.bo.TotalConsumerProgress;
36 | import com.alibaba.rocketmq.web.util.LoggerUtil;
37 | import java.util.ArrayList;
38 | import java.util.Collections;
39 | import java.util.Date;
40 | import java.util.LinkedHashSet;
41 | import java.util.LinkedList;
42 | import java.util.List;
43 | import java.util.Map;
44 | import java.util.Set;
45 | import javax.annotation.PostConstruct;
46 | import javax.annotation.PreDestroy;
47 | import org.springframework.beans.factory.annotation.Value;
48 | import org.springframework.stereotype.Service;
49 |
50 | /**
51 | * 初始化相关业务
52 | * @author xiangnan.wang@ipinyou.com
53 | */
54 | @Service
55 | public class RocketMQService {
56 |
57 | @Value("${rocketmq.namesrv.addr}")
58 | private String nameAddr;
59 |
60 | private DefaultMQAdminExt adminExt;
61 |
62 | @PostConstruct
63 | private void initRocketMQEnv(){
64 | adminExt = new DefaultMQAdminExt();
65 | if(adminExt.getNamesrvAddr()==null||adminExt.getNamesrvAddr().length()>0){
66 | adminExt.setNamesrvAddr(nameAddr);
67 | }
68 | adminExt.setInstanceName(Long.toString(System.currentTimeMillis()));
69 | try {
70 | adminExt.start();
71 | } catch (Exception ex) {
72 | LoggerUtil.getLogger().error("initRocketMQEnv error",ex);
73 | }
74 | }
75 |
76 | /**
77 | * 获取集群信息
78 | * @return
79 | */
80 | public List getClusterInfo(){
81 | List cibl=new ArrayList();
82 | try {
83 | ClusterInfo cinfo = adminExt.examineBrokerClusterInfo();
84 | for(Map.Entry> entry:cinfo.getClusterAddrTable().entrySet()){
85 | String clusterName=entry.getKey();
86 | for(String brokerName:entry.getValue()){
87 | BrokerData bd=cinfo.getBrokerAddrTable().get(brokerName);
88 | for(Map.Entry bentry:bd.getBrokerAddrs().entrySet()){
89 | Map rmap=adminExt.fetchBrokerRuntimeStats(bentry.getValue()).getTable();
90 | double inTps=0d;
91 | double outTps=0d;
92 | try{
93 | {
94 | String tpses=rmap.get("putTps");
95 | String[] tpsArr=tpses.split(" ");
96 | if(tpsArr!=null&&tpsArr.length>0){
97 | inTps=Double.parseDouble(tpsArr[0]);
98 | }
99 | }
100 | {
101 | String tpses=rmap.get("getTransferedTps");
102 | String[] tpsArr=tpses.split(" ");
103 | if(tpsArr!=null&&tpsArr.length>0){
104 | outTps=Double.parseDouble(tpsArr[0]);
105 | }
106 | }
107 | }catch(Exception e){}
108 | ClusterInfoBo cib=new ClusterInfoBo();
109 | cib.setClusterName(clusterName);
110 | cib.setBrokerName(brokerName);
111 | cib.setInTps(inTps);
112 | cib.setOutTps(outTps);
113 | cib.setBid(bentry.getKey().toString());
114 | cib.setVersion(rmap.get("brokerVersionDesc"));
115 | cib.setAddr(bentry.getValue());
116 | cibl.add(cib);
117 | }
118 | }
119 | }
120 | } catch (Exception ex) {
121 | LoggerUtil.getLogger().error("getClusterInfo", ex);
122 | }
123 | return cibl;
124 | }
125 |
126 | /**
127 | * 获取消费进度信息所有的消费组
128 | * @return
129 | */
130 | public List consumerProgress(){
131 | List tcprogressl=new ArrayList();
132 | try {
133 | TopicList topicl=adminExt.fetchAllTopicList();
134 | for(String topic:topicl.getTopicList()){
135 | if(topic.startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)){
136 | String consumerGroup=topic.substring(MixAll.RETRY_GROUP_TOPIC_PREFIX.length());
137 | ConsumeStats consumeStats = null;
138 | try {
139 | consumeStats = adminExt.examineConsumeStats(consumerGroup);
140 | } catch (Exception e) {
141 | LoggerUtil.getLogger().warn("examineConsumeStats exception, " + consumerGroup, e);
142 | }
143 | ConsumerConnection cc = null;
144 | try {
145 | cc = adminExt.examineConsumerConnectionInfo(consumerGroup);
146 | } catch (Exception e) {
147 | LoggerUtil.getLogger().warn("examineConsumerConnectionInfo exception, " + consumerGroup, e);
148 | }
149 | TotalConsumerProgress tcprogress=new TotalConsumerProgress();
150 | tcprogress.setGroup(consumerGroup);
151 | if(consumeStats!=null){
152 | tcprogress.setTps(consumeStats.getConsumeTps());
153 | tcprogress.setDiff(consumeStats.computeTotalDiff());
154 | }
155 | if(cc!=null){
156 | tcprogress.setCount(cc.getConnectionSet().size());
157 | tcprogress.setType(cc.getConsumeType()==ConsumeType.CONSUME_ACTIVELY?"PULL":"PUSH");
158 | tcprogress.setVersion(MQVersion.getVersionDesc(cc.computeMinVersion()));
159 | }
160 | tcprogressl.add(tcprogress);
161 | }
162 | }
163 | } catch (Exception ex) {
164 | LoggerUtil.getLogger().error("consumerProgress()",ex);
165 | }
166 |
167 | return tcprogressl;
168 | }
169 |
170 |
171 | /**
172 | * 获取某个consumergroup的消费明细
173 | * @param consumerGroup 消费组
174 | * @return
175 | */
176 | public SingleConsumerProgress consumerProgress(String consumerGroup){
177 | SingleConsumerProgress sp=new SingleConsumerProgress();
178 | List cdList=new ArrayList();
179 | try {
180 | ConsumeStats stats=adminExt.examineConsumeStats(consumerGroup);
181 | Map m=stats.getOffsetTable();
182 |
183 | List mqList = new LinkedList();
184 | mqList.addAll(stats.getOffsetTable().keySet());
185 | Collections.sort(mqList);
186 |
187 | long diffTotal = 0L;
188 |
189 | for(MessageQueue mq:mqList){
190 | OffsetWrapper offsetWrapper = stats.getOffsetTable().get(mq);
191 | long diff = offsetWrapper.getBrokerOffset() - offsetWrapper.getConsumerOffset();
192 | diffTotal += diff;
193 |
194 | SingleConsumerProgress.ConsumerDetail cd=new SingleConsumerProgress.ConsumerDetail();
195 | cd.setBrokerName(mq.getBrokerName());
196 | cd.setMqId(mq.getQueueId());
197 | cd.setTopic(mq.getTopic());
198 | cd.setBrokerOffset(offsetWrapper.getBrokerOffset());
199 | cd.setConsumerOffset(offsetWrapper.getConsumerOffset());
200 | cd.setDiff(offsetWrapper.getBrokerOffset()-offsetWrapper.getConsumerOffset());
201 | cdList.add(cd);
202 | }
203 | sp.setCdList(cdList);
204 | sp.setTotalDiff(diffTotal);
205 | sp.setTps(stats.getConsumeTps());
206 | } catch (Exception ex) {
207 | LoggerUtil.getLogger().warn("consumerProgress single error:"+consumerGroup,ex);
208 | }
209 | return sp;
210 | }
211 |
212 | /**
213 | * 获取topic列表
214 | * @return
215 | */
216 | public Set getTopics(){
217 | Set topicSet=new LinkedHashSet();
218 | try {
219 | TopicList topicList=adminExt.fetchAllTopicList();
220 | for(String topic:topicList.getTopicList()){
221 | if(!topic.startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)&&
222 | !topic.startsWith(MixAll.DLQ_GROUP_TOPIC_PREFIX)){
223 | topicSet.add(topic);
224 | }
225 | }
226 | } catch (Exception ex) {
227 | LoggerUtil.getLogger().error("getTopics error:",ex);
228 | }
229 | return topicSet;
230 | }
231 |
232 | /**
233 | * 获取topic状态信息
234 | * @param topic topic名称
235 | * @return
236 | */
237 | public List getTopicStats(String topicName){
238 | List tsbList=new ArrayList();
239 | try{
240 | TopicStatsTable tst=adminExt.examineTopicStats(topicName);
241 | List mqList=new LinkedList();
242 | mqList.addAll(tst.getOffsetTable().keySet());
243 | Collections.sort(mqList);
244 | for(MessageQueue mq:mqList){
245 | TopicOffset offset=tst.getOffsetTable().get(mq);
246 | TopicStatsBo tsb=new TopicStatsBo();
247 | tsb.setBrokerName(mq.getBrokerName());
248 | tsb.setQid(mq.getQueueId());
249 | tsb.setMinOffset(offset.getMaxOffset());
250 | tsb.setMaxOffset(offset.getMaxOffset());
251 | tsb.setLastUpdate(new Date(offset.getLastUpdateTimestamp()));
252 | tsbList.add(tsb);
253 | }
254 | }catch(Exception e){
255 | LoggerUtil.getLogger().error("getTopicStats error:",e);
256 | }
257 | return tsbList;
258 | }
259 |
260 | @PreDestroy
261 | public void clean(){
262 | if(adminExt!=null){
263 | adminExt.shutdown();
264 | }
265 | }
266 |
267 | }
268 |
--------------------------------------------------------------------------------