Java-JMX框架探究

简介

JMX(Java Management Extensions) 是一个为应用程序植入管理功能的框架。
JMX 也是一套标准的代理和服务,实际上,用户可以在任何Java应用程序中使用这些代理和服务实现管理资源。

API

JMX 的API 主要在这两个地方:

  • java.lang.management
  • javax.management.*

资源

JMX 涉及到的是监控和管理,那么就会有涉及到管理资源。

我们要做的就是对资源进行监控和管理,监控是为了及时发现问题,以便能够及时提出正确的解决方案,避免损失。管理是为了预防问题的发生,同时也是为了使资源能够得到有效的利用,使利益最大化。
目前,JMX 可以实现的功能有:

  • 监控硬件和平台的运行情况:包括服务器、操作系统等。
  • 合理配置资源:比如内存的配置是否合理,CPU是否足够强大,硬盘容量是否足够。
  • 收集应用运行的情况:比如说访问量多大,响应时间是否够快,哪个地区的访问人数最多。
  • 在应用发生异常时能够及时定位问题所在:这是监控的核心之一。

术语

**管理资源(Manageable Source)**: 能够帮助系统或者你将要发生的活动正常运转的都是资源,这些只要能够被Java 类描述即可。

**管理组件(MBean, managed bean)**: 从资源角度来说,他是一个对抽象资源的一个描述。
由于管理组件是资源的抽象,所以管理应用也是直接面向MBean ,也就是MBean 会暴露给管理应用来操作和访问,通过MBean 中的方法和属性。
MBean 也有很多种类型,例如Standrad MBean、Dynamic MBean、Open MBean(目前还在改进中)、Model MBean。如无特殊说明,一般都是Standrad MBean。

**管理组件服务器(MBean Server)**: 简单来说就是一个容器,用来盛装和管理一组MBeans ,他是整个JMX 管理环境的核心。
由于其中有很多的MBean ,所以提供了一种注册机制来区分各个MBean ,每一个Mbean Server 的MBean 在注册的时候都要提供一个ObjectName 来区分彼此,MBean Server 通过这个ObjectName 来寻找每个MBean ,在JMX 中通过ObjectName 类来为每一个MBean 提供唯一标识,主要包含两部分:

  • 域名: 这个域名就是要注册到MBean Server 中的名称标识相同,以便根据功能区分不同Mbean Server 中的MBean 。
  • 键值对列表: 被用来唯一的标识MBean ,也提供了关于MBean 的相关信息。

当ObjectName 重复时,注册的时候就会抛出javax.management.InstanceAlreadyExistsException 异常。

JMX 代理(JMX Agent): 它提供一系列的服务来管理一系列的Mbeans ,他是MBean Server 的容器。
JMX 代理提供了一些服务,包括创建MBean 之间的关系、动态加载类、简单监视服务、计时器。
代理也可以有一系列的协议适配器(Protocol adapters) 和连接器(connectors) ,协议适配器和连接器也是Java 类,通常情况下也是MBeans ,这些适配器和连接器是提供转接功能而存在的,以便可以在远程使用不同的协议,通过客户端与这个代理连接(内部可以映射到一个外部的协议或者暴露代理给远程连接),这也就意味着JMX 代理可以被一系列的工具和管理协议使用,其本质就是一种
插件式架构
的体现,体现了可插拔的思想。

协议适配器和连接器(Protocol adapters and Connectors): 协议适配器和连接器都是JMX Agent 中的对象,将代理暴露给不同的管理应用和协议,就类似于不同的数据库驱动程序类似。一个JMX Agent 可以有很多个适配器和连接器,他们都是MBeans 。

通知(Notification): 通知是由MBeans 和MBean Server 提出的,其中封装了对应的具体事件和相应的数据。其他的Mbeans 或者Java 对象可以注册监听器来接收这些通知(观察者模式)。


JMX 架构图

1.jpg
由上图,JMX 的架构主要被分成三层:

  • 基础层: 主要是Mbean ,被管理的资源。
  • 适配层: MBean Server ,主要提供对资源的注册和管理。
  • 接入层: 提供远程访问的入口。

简单示例

  1. 建立MBean 接口

    1
    2
    3
    4
    5
    public interface HelloWorldMBean {
    String getGreeting();
    void setGreeting(String greeting);
    void printGreeting();
    }
  2. 实现MBean 接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public class HelloWorld implements HelloWorldMBean {
    private String greeting;

    public HelloWorld(String greeting) {
    this.greeting = greeting;
    }
    public HelloWorld() {
    this.greeting = "hello world!";
    }
    public String getGreeting() {
    return greeting;
    }
    public void setGreeting(String greeting) {
    this.greeting = greeting;
    }
    public void printGreeting() {
    System.out.println(greeting);
    }
    }
  3. 创建MBean Server 和JMX Agent

    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
    public class HelloAgent implements NotificationListener {
    private MBeanServer mbs;

    public HelloAgent() {
    this.mbs = MBeanServerFactory.createMBeanServer("HelloAgent"); // 创建MBean Server,并提供一个名称唯一标识Server

    HelloWorld hw = new HelloWorld(); // 新建创建的MBean
    ObjectName objName = null;
    try{
    objName = new ObjectName("HelloAgent:name=HelloWorld"); // 赋予一个名称唯一标识MBean,使用域名+属性列表来标识
    mbs.registerMbean(hw, objName); // MBean Server 注册MBean
    } catch(Exception e) {
    e.printStackTrace();
    }
    startHtmlAdapterServer();
    }

    public void startHtmlAdapterServer() {
    HtmlAdapterServer server = new HtmlAdapterServer(); // 创建一个Adapter ,便于测试
    ObjectName adapterName = null;
    try{
    adapterName = new ObjectName("HelloAgent:name=adapter,port=9902"); // 赋予唯一标识的名称
    server.setPort(9902); // Adapter 设置端口
    mbs.registerMbean(server, adapterName); // MBean Server 注册Mbean
    server.start(); // Adapter 启动
    } catch(Exception e) {
    e.printStackTrace();
    }
    }

    public static void main(String[] args) {
    System.out.println("HelloAgent is running!");
    HelloAgent agent = new HelloAgent();
    }
    }

    需要引入jmxtools.jar 包到classpath中。


个人备注

此博客内容均为作者学习所做笔记,侵删!
若转作其他用途,请注明来源!