Java远程监控ActiveMQ消息队列

因为公司的产品架构有用到ActiveMQ消息队列,在之前的压力测试上有发现ActiveMQ存在消费不过来的情况,这里记录下在Linux系统下如何实现通过Java对ActiveMQ消息队列的监控。
Java远程监控ActiveMQ消息队列_第1张图片
Java是通过配置JMX来监控ActiveMQ的消息队列的,这里用到消息队列工具类,放下实现类:

import java.io.IOException;
import java.util.PriorityQueue;

import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import org.apache.activemq.broker.jmx.BrokerViewMBean;
import org.apache.activemq.broker.jmx.QueueViewMBean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import cn.itcast.ssm.po.MQQue;

public class ActiveMqKit {

	 
	 	public static final String reportQueueName ="zc-queue-actual";//生成核对报告队列名
	    private static Log log = LogFactory.getLog(ActiveMqKit.class);
	    private static final String connectorPort = "11099";
	    private static final String connectorPath = "/jmxrmi";
	    private static final String jmxDomain = "org.apache.activemq";


	    public static PriorityQueue getAllQueue(String ip)throws Exception {
	        
	        BrokerViewMBean mBean=null;
	        MBeanServerConnection connection=null;
	        PriorityQueue ques=new PriorityQueue();
	        try{
	            JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://"+ip+":" + connectorPort + connectorPath);
	            JMXConnector connector = JMXConnectorFactory.connect(url);
	            connector.connect();
	            connection = connector.getMBeanServerConnection();
	            ObjectName name = new ObjectName(jmxDomain + ":brokerName=localhost,type=Broker");
	            mBean = MBeanServerInvocationHandler.newProxyInstance(connection, name, BrokerViewMBean.class, true);
	        }catch (IOException e){
	            log.error("ActiveMQUtil.getAllQueueSize",e);
	        }catch (MalformedObjectNameException e){
	            log.error("ActiveMQUtil.getAllQueueSize",e);
	        }
	        if(mBean!=null){
	            for (ObjectName queueName : mBean.getQueues()) {
	            	QueueViewMBean  queueMBean = MBeanServerInvocationHandler.newProxyInstance(connection, queueName, QueueViewMBean.class, true);
	                MQQue que=new MQQue();
	                que.setName(queueMBean.getName());
	                que.setQueueSize(queueMBean.getQueueSize());
	                que.setConsumerCount(queueMBean.getConsumerCount());
	                que.setDequeueCount(queueMBean.getDequeueCount());
	                if(ques.size()<=2) {	                
	                ques.add(que);
	                }else {
	                	if(que.getQueueSize()>ques.peek().getQueueSize()) {
	                		ques.poll();
	                		ques.add(que);
	                	}
	                }
	                //System.out.println("Queue Name --- " + queueMBean.getName());// 消息队列名称
	               // System.out.println("Queue Size --- " + queueMBean.getQueueSize());// 队列中剩余的消息数
	                //System.out.println("Number of Consumers --- " + queueMBean.getConsumerCount());// 消费者数
	               // System.out.println("Number of Dequeue ---" + queueMBean.getDequeueCount());// 出队数
	            }
	        }

	        return ques;
	    }      
}

这里有几点说下:
1.mq默认的后台端口号是61616,很多博客上也有写连接端口号是1093的,其实不对,应该是11099,当然可能1093是用于监控Windows系统下的mq的,一开始我照搬一些博客端口号是用1093,结果运行一直报拒绝连接的错误,不明所以,直到用了11099才豁然开朗。
2.mq的消费队列可能有很多,在做性能测试的时候可能重点关注的是发现消费不过来的队列(就是队列中剩余消费数特别多的队列),我在获取到每个队列的信息后用一个MQQue 类进行包装,设置一个大小为2的最小堆,以队列中剩余的消息数为比较找出剩余消费数最多的TOP2队列(消费不过来的队列)。
MQQue类实现如下:

public class MQQue implements Comparable {

	private String name;// 消息队列名称
	private long queueSize;// 队列中剩余的消息数
	private long consumerCount;// 消费者数
	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;
	}
	@Override
	public int compareTo(MQQue o1) {
		// TODO Auto-generated method stub
		long res=this.getQueueSize()-o1.getQueueSize();
		if(res>0) return 1;
		else if(res<0) return -1;
		else return 0;
	}
	
	
}

这样代码就算写完了,但是你以为这样就完事了那真是too young too simple,这样运行程序还是会报错的,在Linux系统下还需要对ActiveMQ修改相应的配置才能开启jmx监控。

1.首先修改/etc目录下的hosts文件:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
将 127.0.0.1修改为 ActiveMQ 所在服务器的ip:
1.32.160.240 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6

2.在activemq文件夹下的conf目录中,找到activemq.xml,在broker节点增加useJmx="true"属性:
在这里插入图片描述
3.继续修改activemq.xml的managementContext 节点:

	   
	
	 

这里的connectorPort="11099"要加上,否则会出现java.lang.RuntimeException: java.rmi.ConnectException: Connection refused to host: 127.0.0.1的错误。

4.在mq的bin 目录的 activemq 文件最后一行加上如下配置:

 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"

5.修改conf目录下jmx.password和jmx.access 文件的权限:
chmod 400 …/conf/jmx.*
这两个文件权限必须是当前用户只读(也就是400)否则会使得activemq无法启动,而且没有任何地方报错。

6.重启mq:
systemctl stop mq;
systemctl start mq;

当环境配置好后再运行前面写的代码,就可以获取到mq的消费者数、剩余消费数、已消费数、队列名称等信息了,实现对ActiveMQ的监控。

你可能感兴趣的:(后端开发)