JMX简介及实践

2024-09-01 00:58
文章标签 实践 简介 jmx

本文主要是介绍JMX简介及实践,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简介

基本术语

  • MBean:是Managed Bean的简称,可以翻译为“管理构件”。在JMX中MBean代表一个被管理的资源实例,通过MBean中暴露的方法和属性,外界可以获取被管理的资源的状态和操纵MBean的行为。事实上,MBean就是一个Java Object,同JavaBean模型一样,外界使用自醒和反射来获取Object的值和调用Object的方法,只是MBean更为复杂和高级一些。MBean通过公共方法以及遵从特定的设计模式封装了属性和操作,以便暴露给管理应用程序。例如,一个只读属性在管理构件中只有Get方法,既有Get又有Set方法表示是一个可读写的属性。一共有四种类型的MBean: Standard MBean, Dynamic MBean, Open MBean, Model MBean。
  • MBeanServer:MBean生存在一个MBeanServer中。MBeanServer管理这些MBean,并且代理外界对它们的访问。并且MBeanServer提供了一种注册机制,是的外界可以通过名字来得到相应的MBean实例。
  • JMX Agent:Agent只是一个Java进程,它包括这个MBeanServer和一系列附加的MbeanService。当然这些Service也是通过MBean的形式来发布。
  • Protocol Adapters and Connectors:MBeanServer依赖于Protocol Adapters和Connectors来和运行该代理的Java虚拟机之外的管理应用程序进行通信。Protocol Adapters通过特定的协议提供了一张注册在MBeanServer的MBean的视图。例如,一个HTML Adapter可以将所有注册过的MBean显示在Web 页面上。不同的协议,提供不同的视图。Connectors还必须提供管理应用一方的接口以使代理和管理应用程序进行通信,即针对不同的协议,Connectors必须提供同样的远程接口来封装通信过程。当远程应用程序使用这个接口时,就可以通过网络透明的和代理进行交互,而忽略协议本身。Adapters和Connectors使MBean服务器与管理应用程序能进行通信。因此,一个代理要被管理,它必须提供至少一个Protocol Adapter或者Connector。面临多种管理应用时,代理可以包含各种不同的Protocol Adapters和Connectors。当前已经实现和将要实现的Protocol Adapters和Connectors包括: RMI Connector, SNMP Adapter, IIOP Adapter, HTML Adapter, HTTP Connector.

Adapter 和Connector的区别在于:Adapter是使用某种Internet协议来与JMX Agent获得联系,Agent端会有一个对象 (Adapter)来处理有关协议的细节。比如SNMP Adapter和HTTP Adapter。而Connector则是使用类似RPC的方式来访问Agent,在Agent端和客户端都必须有这样一个对象来处理相应的请求与应答。比如RMI Connector。

JMX Agent可以带有任意多个Adapter,因此可以使用多种不同的方式访问Agent。

JMX基本构架

JMX分为三层,分别负责处理不同的事务。它们分别是:

  • Instrumentation 层
    Instrumentation层主要包括了一系列的接口定义和描述如何开发MBean的规范。通常JMX所管理的资源有一个或多个MBean组成,因此这个资源可以是任何由Java语言开发的组件,或是一个JavaWrapper包装的其他语言开发的资源。
  • Agent 层
    Agent 用来管理相应的资源,并且为远端用户提供访问的接口。Agent层构建在Intrumentation层之上,并且使用并管理 Instrumentation层内部描述的组件。Agent层主要定义了各种服务以及通信模型。该层的核心是一MBeanServer,所有的MBean都要向它注册,才能被管理。注册在MBeanServer上的MBean并不直接和远程应用程序进行通信,他们通过协议适配器(Adapter)和连接器(Connector)进行通信。通常Agent由一个MBeanServer和多个系统服务组成。JMX Agent并不关心它所管理的资源是什么。
  • Distributed 层
    Distributed层关心Agent如何被远端用户访问的细节。它定义了一系列用来访问Agent的接口和组件,包括Adapter和Connector的描述。

如果一个Java对象可以由一个遵循JMX规范的管理器应用管理,那么这个Java对象就可以由JMX管理资源。要使一个Java对象可管理,则必须创建相应的MBean对象,并通过这些MBean对象管理相应的Java对象。当拥有MBean类后,需要将其实例化并注册到MBeanServer上。

详述

这里采用的是JDK7,JDK7中已经包含了jmx,但是如果用到HtmlAdaptorServer类(后面会看到)还需要用到jmxtools.jar, 可以去这里 下载,有两个包:jmx-1_2_1-ri.zip; jmx_remote-1_0_1_03-ri.zip。jmx-1_2_1-ri.zip解压后lib中有jmxri.jar和jmxtools.jar,将jmxtool.jar拷贝出来放入classpath中即可(jmxri.jar在JDK5+已经包被包含了)。

Standard MBean

Standard MBean的设计和实现是最简单的,它们的管理接口通过方法名来描述。Standard MBean的实现依靠一组命名规则,称之为设计模式。这些命名规则定义了属性和操作。

检查Standard MBean接口和应用设计模式的过程被称为内省(Introspection)。JMX代理通过内省来查看每一个注册在MBeanServer上的MBean的方法和超类,看它是否遵从一定设计模式,决定它是否代表了一个MBean,并辨认出它的属性和操作。

Standard MBean是JMX管理构件中最简单的一种,只需要开发一个MBean接口(为了实现Standard MBean,必须遵循一套继承规范。必须每一个MBean定义一个接口,而且这个接口的名字必须是其被管理的资源的对象类的名称后面加上”MBean”),一个实现MBean接口的类,并且把它们注册到MBeanServer中就可以了。

package com.test.jmx;public interface HelloMBean {public String getName();public void setName(String name);public void printHello();public void printHello(String whoName);
}

接下来是真正的资源对象,因为命名规范的限制,因此对象名称必须为Hello.

package com.test.jmx;public class Hello implements HelloMBean {private String name;@Overridepublic String getName() {return name;}@Overridepublic void setName(String name) {this.name = name;}@Overridepublic void printHello() {System.out.println("Hello world, "+ name);}@Overridepublic void printHello(String whoName) {System.out.println("Hello, "+whoName);}
}

接下去创建一个Agent类:

package com.test.jmx;import com.sun.jdmk.comm.HtmlAdaptorServer;import javax.management.*;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;public class HelloAgent {public static void main(String[] args) throws MalformedObjectNameException,NotCompliantMBeanException, InstanceAlreadyExistsException,MBeanRegistrationException, IOException {// 下面这种方式不能再JConsole中使用
//      MBeanServer server = MBeanServerFactory.createMBeanServer();
// 首先建立一个MBeanServer,MBeanServer用来管理我们的MBean,通常是通过MBeanServer来获取我们MBean的信息,间接
// 调用MBean的方法,然后生产我们的资源的一个对象。MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();String domainName = "MyMBean";//为MBean(下面的new Hello())创建ObjectName实例ObjectName helloName = new ObjectName(domainName+":name=HelloWorld");
// 将new Hello()这个对象注册到MBeanServer上去mbs.registerMBean(new Hello(),helloName);// Distributed Layer, 提供了一个HtmlAdaptor。支持Http访问协议,并且有一个不错的HTML界面,这里的Hello就是用这个作为远端管理的界面
// 事实上HtmlAdaptor是一个简单的HttpServer,它将Http请求转换为JMX Agent的请求ObjectName adapterName = new ObjectName(domainName+":name=htmladapter,port=8082");HtmlAdaptorServer adapter = new HtmlAdaptorServer();adapter.start();mbs.registerMBean(adapter,adapterName);int rmiPort = 1099;Registry registry = LocateRegistry.createRegistry(rmiPort);JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:"+rmiPort+"/"+domainName);JMXConnectorServer jmxConnector = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);jmxConnector.start();}
}

编译运行,在浏览器中输入localhost:8082,这样我们就可以对程序进行管理,如图:

可以看到我们注册的MyMBean域下的”name=HelloWorld”,可以点击进去,然后可以修改属性Name和执行2个printHello方法,可以在控制台看到效果。具体不贴图赘述,机智的小伙伴一试就知道怎么玩转了。

上面代码中还通过RMI(JMXServiceURL, JMXConnectorServer )注册URL来提供客户端连接,可以通过JConsole作为客户端来管理MBean. 打开JConsole工具(%JAVA_HOME%/bin/jconsole.exe),如图在远程进程中输入rmi地址“service:jmx:rmi:///jndi/rmi://localhost:1099/MyMBean”:

点击“连接”之后就出现:

这样就可以像HTML一样管理MBean了。

注意上面的代码中:

Registry registry = LocateRegistry.createRegistry(rmiPort);

可以在某一特定端口创建名字夫妇,从而用户无需再手工启动rmiregistry,如果不加入这句代码,就会出现Connection Refused的异常:

Exception in thread "main" java.io.IOException: Cannot bind to URL [rmi://localhost:1099/MyMBean]: javax.naming.ServiceUnavailableException [Root exception is java.rmi.ConnectException: Connection refused to host: localhost; nested exception is: java.net.ConnectException: Connection refused: connect]at javax.management.remote.rmi.RMIConnectorServer.newIOException(Unknown Source)at javax.management.remote.rmi.RMIConnectorServer.start(Unknown Source)at com.test.jmx.HelloAgent.main(HelloAgent.java:44)
Caused by: javax.naming.ServiceUnavailableException [Root exception is java.rmi.ConnectException: Connection refused to host: localhost; nested exception is: java.net.ConnectException: Connection refused: connect]at com.sun.jndi.rmi.registry.RegistryContext.bind(Unknown Source)at com.sun.jndi.toolkit.url.GenericURLContext.bind(Unknown Source)at javax.naming.InitialContext.bind(Unknown Source)at javax.management.remote.rmi.RMIConnectorServer.bind(Unknown Source)... 2 more
Caused by: java.rmi.ConnectException: Connection refused to host: localhost; nested exception is: java.net.ConnectException: Connection refused: connectat sun.rmi.transport.tcp.TCPEndpoint.newSocket(Unknown Source)at sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source)at sun.rmi.transport.tcp.TCPChannel.newConnection(Unknown Source)at sun.rmi.server.UnicastRef.newCall(Unknown Source)at sun.rmi.registry.RegistryImpl_Stub.bind(Unknown Source)... 6 more
Caused by: java.net.ConnectException: Connection refused: connectat java.net.DualStackPlainSocketImpl.connect0(Native Method)at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)at java.net.AbstractPlainSocketImpl.connect(Unknown Source)at java.net.PlainSocketImpl.connect(Unknown Source)at java.net.SocksSocketImpl.connect(Unknown Source)at java.net.Socket.connect(Unknown Source)at java.net.Socket.connect(Unknown Source)at java.net.Socket.<init>(Unknown Source)at java.net.Socket.<init>(Unknown Source)at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(Unknown Source)at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(Unknown Source)... 11 more

当然,这也就其他的解决办法:运行 %JAVA_HOME%/bin/rmiregistry.exe 1099就有和那行代码一样的效果。

我们不仅可以通过JConsole作为客户端采用rmi的方式来进行管理,我们同样可以采用自定义程序作为客户端来连接JMXConnectorServer管理MBean.

package com.test.jmx;import java.io.IOException;
import java.util.Iterator;
import java.util.Set;import javax.management.Attribute;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;public class Client {public static void main(String[] args) throws IOException,MalformedObjectNameException, InstanceNotFoundException,AttributeNotFoundException, InvalidAttributeValueException,MBeanException, ReflectionException, IntrospectionException {String domainName = "MyMBean";int rmiPort = 1099;JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:"+rmiPort+"/"+domainName);// 可以类比HelloAgent.java中的那句:// JMXConnectorServer jmxConnector = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);JMXConnector jmxc = JMXConnectorFactory.connect(url);MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();//print domainsSystem.out.println("Domains:------------------");String domains[] = mbsc.getDomains();for(int i=0;i<domains.length;i++){System.out.println("\tDomain["+i+"] = "+domains[i]);}//MBean countSystem.out.println("MBean count = "+mbsc.getMBeanCount());//process attributeObjectName mBeanName = new ObjectName(domainName+":name=HelloWorld");mbsc.setAttribute(mBeanName, new Attribute("Name","zzh"));//注意这里是Name而不是nameSystem.out.println("Name = "+mbsc.getAttribute(mBeanName, "Name"));//接下去是执行Hello中的printHello方法,分别通过代理和rmi的方式执行//via proxyHelloMBean proxy = MBeanServerInvocationHandler.newProxyInstance(mbsc, mBeanName, HelloMBean.class, false);proxy.printHello();proxy.printHello("jizhi boy");//via rmimbsc.invoke(mBeanName, "printHello", null, null);mbsc.invoke(mBeanName, "printHello", new String[]{"jizhi gril"}, new String[]{String.class.getName()});//get mbean informationMBeanInfo info = mbsc.getMBeanInfo(mBeanName);System.out.println("Hello Class: "+info.getClassName());for(int i=0;i<info.getAttributes().length;i++){System.out.println("Hello Attribute:"+info.getAttributes()[i].getName());}for(int i=0;i<info.getOperations().length;i++){System.out.println("Hello Operation:"+info.getOperations()[i].getName());}//ObjectName of MBeanSystem.out.println("all ObjectName:--------------");Set<ObjectInstance> set = mbsc.queryMBeans(null, null);for(Iterator<ObjectInstance> it = set.iterator();it.hasNext();){ObjectInstance oi = it.next();System.out.println("\t"+oi.getObjectName());}jmxc.close();}
}

运行结果:

Domains:------------------Domain[0] = MyMBeanDomain[1] = java.nioDomain[2] = JMImplementationDomain[3] = com.sun.managementDomain[4] = java.langDomain[5] = java.util.logging
MBean count = 21
Name = zzh
Hello Class: com.test.jmx.Hello
Hello Attribute:Name
Hello Operation:printHello
Hello Operation:printHello
all ObjectName:--------------java.lang:type=OperatingSystemjava.lang:type=Compilationjava.lang:type=MemoryPool,name=PS Old Genjava.lang:type=MemoryJMImplementation:type=MBeanServerDelegatejava.lang:type=MemoryPool,name=PS Perm Genjava.lang:type=RuntimeMyMBean:name=htmladapter,port=8082java.nio:type=BufferPool,name=directjava.lang:type=GarbageCollector,name=PS MarkSweepjava.nio:type=BufferPool,name=mappedjava.lang:type=Threadingcom.sun.management:type=HotSpotDiagnosticjava.lang:type=GarbageCollector,name=PS ScavengeMyMBean:name=HelloWorldjava.lang:type=ClassLoadingjava.lang:type=MemoryPool,name=PS Survivor Spacejava.lang:type=MemoryManager,name=CodeCacheManagerjava.lang:type=MemoryPool,name=Code Cachejava.util.logging:type=Loggingjava.lang:type=MemoryPool,name=PS Eden Space

这是客户端的运行结果,由于在客户端调用了服务端的方法,可以在服务端看到打印结果:

Hello world, zzh
Hello, jizhi boy
Hello world, zzh
Hello, jizhi gril

上面代码涉及到辅助原数据的概念:辅助元数据类用来描述管理构件。辅助元数据类不仅被用来内省标准管理构件,也被动态管理构件用来进行自我描述。这些类根据属性、操作、构建器和通告描述了管理接口。JMX代理通过这些元数据类管理所有管理构件,而不管这些管理构件的类型。部分辅助元类如下:

  1. MBeanInfo–包含了属性、操作、构建器和通知的信息。
  2. MBeanFeatureInfo–为下面类的超类。
  3. MBeanAttributeInfo–用来描述管理构件中的属性。
  4. MBeanConstructorInfo–用来描述管理构件中的构建器。
  5. MBeanOperationInfo–用来描述管理构件中的操作。
  6. MBeanParameterInfo–用来描述管理构件操作或构建器的参数。
  7. MBeanNotificationInfo–用来描述管理构件发出的通知。

有关Notication, Dynamic MBean, Model MBean以及Apache Common Modeler由于篇幅限制将后面文章中讲述。

参考资料

  1. JMX整理
  2. JMX简介
  3. http://blog.csdn.net/DryKillLogic/article/category/762777
  4. 用Apache的commons-modeler来辅助开发JMX 

本系列:

  • 从零开始玩转JMX(1):简介和 Standard MBean

转载自:http://www.tuicool.com/articles/feqiEvM

这篇关于JMX简介及实践的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1125495

相关文章

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

ASIO网络调试助手之一:简介

多年前,写过几篇《Boost.Asio C++网络编程》的学习文章,一直没机会实践。最近项目中用到了Asio,于是抽空写了个网络调试助手。 开发环境: Win10 Qt5.12.6 + Asio(standalone) + spdlog 支持协议: UDP + TCP Client + TCP Server 独立的Asio(http://www.think-async.com)只包含了头文件,不依

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

业务协同平台--简介

一、使用场景         1.多个系统统一在业务协同平台定义协同策略,由业务协同平台代替人工完成一系列的单据录入         2.同时业务协同平台将执行任务推送给pda、pad等执行终端,通知各人员、设备进行作业执行         3.作业过程中,可设置完成时间预警、作业节点通知,时刻了解作业进程         4.做完再给你做过程分析,给出优化建议         就问你这一套下

容器编排平台Kubernetes简介

目录 什么是K8s 为什么需要K8s 什么是容器(Contianer) K8s能做什么? K8s的架构原理  控制平面(Control plane)         kube-apiserver         etcd         kube-scheduler         kube-controller-manager         cloud-controlle

【Tools】AutoML简介

摇来摇去摇碎点点的金黄 伸手牵来一片梦的霞光 南方的小巷推开多情的门窗 年轻和我们歌唱 摇来摇去摇着温柔的阳光 轻轻托起一件梦的衣裳 古老的都市每天都改变模样                      🎵 方芳《摇太阳》 AutoML(自动机器学习)是一种使用机器学习技术来自动化机器学习任务的方法。在大模型中的AutoML是指在大型数据集上使用自动化机器学习技术进行模型训练和优化。

Prometheus与Grafana在DevOps中的应用与最佳实践

Prometheus 与 Grafana 在 DevOps 中的应用与最佳实践 随着 DevOps 文化和实践的普及,监控和可视化工具已成为 DevOps 工具链中不可或缺的部分。Prometheus 和 Grafana 是其中最受欢迎的开源监控解决方案之一,它们的结合能够为系统和应用程序提供全面的监控、告警和可视化展示。本篇文章将详细探讨 Prometheus 和 Grafana 在 DevO

springboot整合swagger2之最佳实践

来源:https://blog.lqdev.cn/2018/07/21/springboot/chapter-ten/ Swagger是一款RESTful接口的文档在线自动生成、功能测试功能框架。 一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务,加上swagger-ui,可以有很好的呈现。 SpringBoot集成 pom <!--swagge

SaaS、PaaS、IaaS简介

云计算、云服务、云平台……现在“云”已成了一个家喻户晓的概念,但PaaS, IaaS 和SaaS的区别估计还没有那么多的人分得清,下面就分别向大家普及一下它们的基本概念: SaaS 软件即服务 SaaS是Software-as-a-Service的简称,意思是软件即服务。随着互联网技术的发展和应用软件的成熟, 在21世纪开始兴起的一种完全创新的软件应用模式。 它是一种通过Internet提供

vue2实践:el-table实现由用户自己控制行数的动态表格

需求 项目中需要提供一个动态表单,如图: 当我点击添加时,便添加一行;点击右边的删除时,便删除这一行。 至少要有一行数据,但是没有上限。 思路 这种每一行的数据固定,但是不定行数的,很容易想到使用el-table来实现,它可以循环读取:data所绑定的数组,来生成行数据,不同的是: 1、table里面的每一个cell,需要放置一个input来支持用户编辑。 2、最后一列放置两个b