JMX远程监控ActiveMQ设置
本地消息队列:我们在下载好的 activemq 文件夹下的 config 文件夹下,找到 activemq.bat 文件运行,浏览器访问 http://activemq-host:8161/admin。
activemq-host 是启动机器的 ip 地址,8161 是 activemq 的默认端口号,默认用户名和密码是 admin。会进入一下界面:
当然,这是本地的消息队列,访问,我们启动之后也可以通过 jdk 自带的 jconsole 来监控。这里重点介绍怎样远程监控 activemq。
远程监控 activemq:这里涉及到 JMX 的概念,网上我也搜了很多,我也看的不是很明白,这里大家知道由 Java 开发的程序,一般都是 jmx 来监控就可以了,当然,activemq 也是通过 Jmx 来监控的。这里首先我们来配置一些东西。
1. 在你下载 activemq 文件夹下的 config 中,找到 activemq.xml,在 broker 节点增加 useJmx="true"
2. 在 managementContext 节点更改成下面的截图的样子(这里我直接截图了,增加的东西不多,我就不把能复制的放进来了,自己敲敲,熟悉一下~)
3. 在你 activemq 文件夹下的 bin 找到 activemq(${active_home}/bin/activemq),找到下面截图中出出现的代码,应该是注释掉的,解除注释就行了,我下载的版本是 5.13.4,有的没有下面的代码,不知道是什么原因,这个弄明白之后,会再更新。
代码版 (这个可以直接粘贴过去):
1 2 3 4
| ACTIVEMQ_SUNJMX_START="-Dcom.sun.management.jmxremote.port=11099" ACTIVEMQ_SUNJMX_START="$ACTIVEMQ_SUNJMX_START -Dcom.sun.management.jmxremote.password.file=${ACTIVEMQ_CONF}/jmx.password" ACTIVEMQ_SUNJMX_START="$ACTIVEMQ_SUNJMX_START -Dcom.sun.management.jmxremote.access.file=${ACTIVEMQ_CONF}/jmx.access" ACTIVEMQ_SUNJMX_START="$ACTIVEMQ_SUNJMX_START -Dcom.sun.management.jmxremote.ssl=false"
|
截图版:
4. 在 Linux 上进入 ${active_home}/bin 中执行 chmod 655 activemq
用来获取 active 的权限,我们解压 activemq 之后,发现在 bin 的 activemq 是灰色,不能正常启动就执行 activemq restart
这条命令。执行完这条命令之后,会变成绿色。
然后执行 chmod 400 ${activemq_home}/conf/jmx
. 意思是设置当前用户只读,其他用户没有权限。
接下来在 ${activemq_home}/bin 下执行 activemq start
或者 activemq restart
,一般在前面加 sudo,一般用户没权限。
activemq stop 来停止或者用 ps 显示当前运行的 activemq 的线程号,然后 kill 即可。
好了,接下来,我们来用 jdk 自带的 jconsole 来检测一下。
默认用户名:admin
密码:activemq
这里有可能出现还远程不上的情况:这里有我尝试了下有两种解决办法
- 关闭远程服务器上的防火墙 (当然,这个不推荐,容易被黑客攻击)
- 修改 hosts 文件,添加远程实际的 Ip 地址
当然,我们在实际项目中可能不单单登录 activemq 的 web console 或者 jconsole 来实现监控,我在项目中就是用 java 程序来实现跟 web console 一样的页面展示的形式。接下来引用我实际项目中的代码。
controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| String surl = Constant.MQ_URL; String userName = Constant.MQ_USERNAME; String userPwd = Constant.MQ_USERPWD; Map<String, String[]> env = new HashMap<>(); String[] credentials = {userName, userPwd}; env.put(JMXConnector.CREDENTIALS, credentials); JMXServiceURL url = new JMXServiceURL(surl); JMXConnector jmxc = JMXConnectorFactory.connect(url, env); MBeanServerConnection mbsc = jmxc.getMBeanServerConnection(); ObjectName mbeanName = new ObjectName("org.apache.activemq:brokerName=localhost,type=Broker"); BrokerViewMBean mbean =(BrokerViewMBean) MBeanServerInvocationHandler.newProxyInstance(mbsc, mbeanName, BrokerViewMBean.class, true); List<MqModel> mqList = new ArrayList<MqModel>(); OrganizationService organizationService = (OrganizationService) SpringBeanUtil.getBean("organizationService"); for (ObjectName na : mbean.getQueues()) { QueueViewMBean queueBean = (QueueViewMBean)MBeanServerInvocationHandler.newProxyInstance(mbsc, na, QueueViewMBean.class, true); MqModel mq = new MqModel(); Organization organ = organizationService.getOrganization(queueBean.getName()); if(organ!=null){ mq.setName(organ.getOrgName()); }else{ mq.setName(queueBean.getName()); } mq.setQueueSize(queueBean.getQueueSize()); mq.setConsumerCount(queueBean.getConsumerCount()); mq.setDequeueCount(queueBean.getDequeueCount()); mq.setEnqueueCount(queueBean.getEnqueueCount()); queueBean.getEnqueueCount(); mqList.add(mq); }
|
上面的代码中获取实际数据通过 queueBean.__来获取,这里我用一个 model 来接收了。下面会引入 model 的代码
Constant:
1 2 3
| public static final String MQ_URL = properties.getProperty("mq.url"); public static final String MQ_USERNAME = properties.getProperty("mq.userName"); public static final String MQ_USERPWD = properties.getProperty("mq.userPwd");
|
Model:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
|
public class MqModel { private String name; private Long queueSize; private Long consumerCount; private Long enqueueCount; private Long dequeueCount; public String getName() { return name; } public void setName(String name) { this.name = name; } public Long getQueueSize() { return queueSize; } public void setQueueSize(Long queueSize) { this.queueSize = queueSize; } public Long getConsumerCount() { return consumerCount; } public void setConsumerCount(Long consumerCount) { this.consumerCount = consumerCount; } public Long getDequeueCount() { return dequeueCount; } public void setDequeueCount(Long dequeueCount) { this.dequeueCount = dequeueCount; } public Long getEnqueueCount() { return enqueueCount; } public void setEnqueueCount(Long enqueueCount) { this.enqueueCount = enqueueCount; } }
|
application.properties:
1 2 3 4
| #消息队列服务配置 my.url = service:jmx:rmi:///jndi/rmi://198.9.4.167:11099/jmxrmi mq.userName = admin mq.userPwd = activemq
|
最后,说下我遇到的问题:
在刚接到这个需求的时候,我搜了很多,把 activemq 的远程配置第一步完成之后,发现用代码在 java 程序中控制台总是报权限的错误,不知道为什么,配置也配置好了,后来在 stackoverflow 看到其他程序猿也遇到这个问题,我看他们怎么实现,修改了下我的代码,就可以了。controller 注释的部分是我以前的代码。
1 2 3
| Map<String, String[]> env = new HashMap<>(); String[] credentials = {userName, userPwd}; env.put(JMXConnector.CREDENTIALS, credentials);
|
我发现必须把 activemq 远程的用户名和密码放在 map 才可以~~~~