最近在看flume的监控源码,发现flume的监控metrics是存放在MBean中,再由web服务暴露到其他监控系统中。这次又get到了一个新知识点,今天给大家分享一下。
什么是JMX和MBean?
JMX(Java管理扩展)提供了一种简单的、基础的方法,用来管理诸如应用、设备和服务等资源。由于JMX技术是动态的,你可以使用JMX技术来监控和管理处于创建、安装和运行态的资源。你甚至可以使用JMX技术监控和管理Java虚拟机。我们通过一些监控程序获取到当前JVM的一些状态值,就是通过mbean暴露。下面的内存统计可以查看实时的堆内存使用量。

MBean是一个被管理的Java对象,它遵从JMX规范。MBean可以表示设备、应用或者任何需要被管理的资源。
MBeans暴露如下管理接口:
- 一组可读或者可写属性,通过可写属性可以从外部操作JVM里面的行为,例如执行GC。
- 一组调用方法。
- 自我描述。
例如下面的mbean,可以操作JVM 的GC

如何使用MBean
下面通过一个实例,介绍怎么向JMX注册MBean。
按照约定,MBean接口的名称由其实现类名+MBean后缀组成。根据JMX规范,MBean接口由属性(可读getter方法或者可写setter方法)和操作(暴露的方法)组成。
下面代码将定义一个channel的指标MBean,获取启动时间、结束时间、连接数
1public interface ChannelMetricsMBean { 2 long getStartTime(); 3 4 long getStopTime(); 5 6 long getConnectionCount(); 7} 8 9public class ChannelMetrics implements ChannelMetricsMBean { 10 11 private AtomicLong counter = new AtomicLong(0); 12 13 private long startTime = 0; 14 private long stopTime = 0; 15 16 public void start() { 17 // to do init 18 startTime = System.currentTimeMillis(); 19 } 20 21 public void stop() { 22 stopTime = System.currentTimeMillis(); 23 } 24 25 public void addConnectionCount() { 26 counter.incrementAndGet(); 27 } 28 29 @Override 30 public long getStartTime() { 31 return startTime; 32 } 33 34 @Override 35 public long getStopTime() { 36 return stopTime; 37 } 38 39 @Override 40 public long getConnectionCount() { 41 return counter.get(); 42 } 43}
将mbean注册到 JMX
1public class MBeanMain { 2 public static void main(String[] args) throws MalformedObjectNameException, NotCompliantMBeanException, InstanceAlreadyExistsException, MBeanRegistrationException { 3 4 MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); 5 6 // 注册被管理的对象 7 ObjectName objectName = new ObjectName("test.mbean.channel:type=test1"); 8 ChannelMetrics channelMetrics = new ChannelMetrics(); 9 mBeanServer.registerMBean(channelMetrics, objectName); 10 11 runMonitor(channelMetrics); 12 13 try { 14 Thread.sleep(1000000); 15 } catch (InterruptedException e) { 16 e.printStackTrace(); 17 } 18 } 19 20 private static void runMonitor(ChannelMetrics channelMetrics) { 21 channelMetrics.start(); 22 23 //每10秒添加一个连接 24 ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); 25 executorService.scheduleAtFixedRate(new Runnable() { 26 @Override 27 public void run() { 28 System.out.println("add one connection"); 29 channelMetrics.addConnectionCount(); 30 } 31 }, 1, 10, TimeUnit.SECONDS); 32 33 } 34}
我们可以通过jconsole看下效果
