JMX 监测规范

MBean 监测 ( instrumentation )

在JMX规范的测量仪层面,定义了怎么样去测量Java语言的程序的资源,以至于这些资源能够被管理。实现了资源和测量仪的 Java 对象被称为管理 Bean 或者 MBean, MBean必须遵从设计模式和规范的接口定义。确保所有的MBean提供管理资源的测量的标准 。

定义

MBean是一个具体的 Java 类,包含一下的测量仪。

  • 实现对应的 MBean 接口或者实现 DynamicMBean 接口

  • 可选,实现 NotificationBroadcaster 接口

一个类实现了MBean接口称为 Standard MBean,当开发一个新的JMX可管理的资源,这是一个最简单的测量仪。MBean实现了一个 DynamicMBean 接口即为 Dynamic MBean,这些元素能在运行时能够测量。

Standard MBeans

标准 MBean的管理接口

  • 构造方法:只有MBean public的构造方法暴露
  • 属性:通过getter和setter方法暴露
  • 操作:MBean 剩余的方法暴露
  • 通知:MBean的广播来通知对象和类型

检查 MBean 接口和应用设计模式的过程,称为内省( introspection )

MBean Interface

一个MBean接口名字的形式,是一个以 MBean 结尾,例如 MyClass 实现MBean接口的类为 MyClassMBean

Dynamic MBeans

动态的MBean是资源,在运行时,能够通过预定义的暴露的属性或者操作接口来进行测量。

interface DynamicMBean {
    getMBeanInfo(): MBeanInfo
    getAttribute( attribute:String ): Object
    getAttributes( attributes:String[] ): AttributeList
    setAttribute( attribute:Attribute ): void
    setAttributes( attributes:AttributeList ): AttributeList
    invoke( actionName:String,
    params:Object[],
    signature:String[] ): Object
}

JMX 通知模型

一个 MBean 的管理接口允许它的代理能够控制和配置操作这些管理资源。然而,仅提供了一部分的必要的功能接口去管理复杂分布式系统。常见的,当处理资源的时候,管理应用对于状态的改变或者指定状态,需要作出反应。
JMX 通知以来一下的组件:

  • 一个普通的事件类型,Notification , 能够通知任何的管理事件类型。
  • NotificationListener 接口,对象请求实现去接受 MBean 发送的通知。
  • NotificationFilter 接口,需要对象去实现称为 notification filter
  • NotificationBroadcaster 接口,每个MBean需要实现发送通知。
  • NotificationEmitter 接口,继承 NotificationBroadcaster 当移除监听器,允许控制更多的监听器。

MBean 元数据类型

可以通过一下的类来获取 MBean 的元数据

  • MBeanInfo
  • MBeanFeatureInfo
  • MBeanAttributeInfo
  • MBeanConstructorInfo
  • MBeanOperationInfo
  • MBeanParameterInfo
  • MBeanNotificationInfo

Open MBeans

Open MBeans 的目标是提供一种机制,让管理应用程序和他们的人类管理员能够理解并在运行时发现新管理的对象。
Open MBean 必须具备以下属性:

  • 必须实现 DynamicMBean 接口
  • 所有的属性,方法参数,以及非void的返回值的对象类型是在open MBean 基础类型中。
  • getMBeanInfo 方法必须实现,并且返回类的实例,实现 OpenMBeanInfo 接口的实例。
  • 需要实现一下的方法
    • OpenMBeanInfo.getDescription
    • OpenMBeanOperationInfo.getDescription
    • OpenMBeanConstructorInfo.getDescription
    • OpenMBeanParameterInfo.getDescription
    • OpenMBeanAttributeInfo.getDescription
    • MBeanNotificationInfo.getDescription
    • OpenMBeanOperationInfo.getImpact 实例必须返回 ACTION, INFO, or ACTION_INFO 其中的一个常量。

Model MBeans

模型 MBean 是通用,可配置的 MBean,任何人都可以快速的测试任何资源。
这个 model MBean 定义了一组接口,对于管理资源提供管理模版。它也提供了一组具体的实现类与JMX 代理组合。JMX 代理必须一个实现 javax.management.modelmbean.RequiredModelMBean , 便于使用和拓展。这个 MBean 服务器对model MBean 是一个仓库和工厂。

普通的通知

ModelMBean 接口继承 ModelMBeanNotificationBroadcaster 接口,接口中定义了sendNotification 方法,发送 Notification 对象给所有已注册的监听器。

动态MBean增加操作实例

增加依赖

<dependency>
            <groupId>org.glassfish.external</groupId>
            <artifactId>opendmk_jdmkrt_jar</artifactId>
            <version>1.0-b01-ea</version>
        </dependency>

HelloDynamic.java

public class HelloDynamic implements DynamicMBean {

    private MBeanInfo mBeanInfo = null;

    private String name;

    private String className;

    private String description;

    private MBeanAttributeInfo[] attributes;

    private MBeanConstructorInfo[] constructors;

    private MBeanOperationInfo[] operations;

    private MBeanNotificationInfo[] notifications;

    public HelloDynamic(String name) {
        this.name = name;
        init();
        buildDynamicMBean();
    }

    private void init() {
        className = this.getClass().getName();
        description = "Dynamic MBean";
        // 初始化
        attributes = new MBeanAttributeInfo[1];
        constructors = new MBeanConstructorInfo[1];
        operations = new MBeanOperationInfo[1];

        notifications = new MBeanNotificationInfo[0];

    }

    private void buildDynamicMBean() {
        // 设置构造方法
        Constructor[] constructors2 = this.getClass().getConstructors();
        constructors[0] = new MBeanConstructorInfo("HelloDynamic#Constructor", constructors2[0]);
        // 设置属性
        attributes[0] = new MBeanAttributeInfo("Name", "java.lang.String", "Name:java.lang.String", true, true, false);
        // 设置方法
        operations[0] = new MBeanOperationInfo("print", "print method", null, "void", MBeanOperationInfo.INFO);
        mBeanInfo = new MBeanInfo(className, description, attributes, constructors, operations, notifications);
    }

    //动态增加一个 printString 方法
    private void dynamicAddOperation() {
        init();
        operations = new MBeanOperationInfo[2];//设定数组为两个
        buildDynamicMBean();
        operations[1] = new MBeanOperationInfo(
                "printString",
                "printString() method",
                null,
                "void",
                MBeanOperationInfo.INFO);
        mBeanInfo = new MBeanInfo(
                className,
                description,
                attributes,
                constructors,
                operations,
                notifications);
    }

    @Override
    public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException {
        if (attribute != null) {
            return null;
        }
        if (attribute.equals("Name")) {
            return name;
        }
        return null;
    }

    @Override
    public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
        if (attribute == null)
            return;
        String name = attribute.getName();
        Object value = attribute.getValue();
        try {
            if (name.equals("Name")) {
                if (value == null) {
                    name = null;
                } else if (Class.forName("java.lang.String").isAssignableFrom(value.getClass())) {
                    name = (String) value;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public AttributeList getAttributes(String[] attributes) {
        if (attributes == null)
            return null;
        AttributeList resultList = new AttributeList();
        if (attributes.length == 0)
            return resultList;
        for (int i = 0; i < attributes.length; i++) {
            try {
                Object value = getAttribute(attributes[i]);
                resultList.add(new Attribute(attributes[i], value));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return resultList;
    }

    @Override
    public AttributeList setAttributes(AttributeList attributes) {
        if (attributes == null)
            return null;
        AttributeList resultList = new AttributeList();
        // if attributeNames is empty, nothing more to do
        if (attributes.isEmpty())
            return resultList;
        // for each attribute, try to set it and add to the result list if successful
        attributes.forEach(attr -> {
            try {
                setAttribute((Attribute) attr);
                String name = ((Attribute) attr).getName();
                Object value = getAttribute(name);
                resultList.add(new Attribute(name, value));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        return resultList;
    }

    @Override
    public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException {
        if(actionName.equals("print")){
            System.out.println("Hello, " + name + ", this is HellDynamic!");
            //增加新方法
            dynamicAddOperation();
            System.out.println("add Operation successful");
        }else if(actionName.equals("printString")){
            System.out.println("execute printString operation");
        }
        return null;
    }

    @Override
    public MBeanInfo getMBeanInfo() {
        return mBeanInfo;
    }
}

DynamicAgent.java

public class DynamicAgent {

    public static void main(String[] args) throws Exception {
        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
        ObjectName objectName = new ObjectName("MyMBean:name=hello");
        HelloDynamic helloDynamic = new HelloDynamic("DynamicMBean");
        server.registerMBean(helloDynamic, objectName);

        ObjectName adapterName = new ObjectName("DynamicAgent:name=htmladapter,port=8082");
        HtmlAdaptorServer htmlServer = new HtmlAdaptorServer();

        server.registerMBean(htmlServer, adapterName);

        htmlServer.start();

        System.out.println("server start...");

    }
}

浏览器访问localhost:8082,通过执行print方法动态增加printString方法。
111111.jpg

22222.jpg

33333.jpg

添加新评论