【Java基础】你听说过JMX么
什么是jmx
jmx(java管理扩展),是一套给应用程序引入监控管理功能的接口。比如我们可以通过jmx来监控tomcat的运行状态。jmx最主要的应用场景就是中间件的监控,配置文件的在线修改配置。
相关概念
一个典型的jmx架构图:
mbean:是managed bean的简称。在jmx中mbean代表一个被管理的资源实例,通过mbean中暴露的方法和属性,外界可以获取被管理的资源的状态和操纵mbean的行为。事实上,mbean就是一个java object,同javabean模型一样,外界使用自醒和反射来获取object的值和调用object的方法,只是mbean更为复杂和高级一些。
mbeanserver:mbean生存在一个mbeanserver中。mbeanserver管理这些mbean,并且代理外界对它们的访问。并且mbeanserver提供了一种注册机制,是的外界可以通过名字来得到相应的mbean实例。
jmx agent:agent只是一个java进程,它包括这个mbeanserver和一系列附加的mbeanservice。当然这些service也是通过mbean的形式来发布。
objectname:mbean在mbeanserver中的唯一标识。
protocol adapters and connectors
jmx agent通过各种各样的adapter和connector来与外界(jvm之外)进行通信。同样外界(jvm之外)也必须通过某个adapter和connector来向jmx agent发送管理或控制请求。
adapter和connector的区别在于:adapter是使用某种internet协议来与jmx agent获得联系,agent端会有一个对象(adapter)来处理有关协议的细节。比如snmp adapter和http adapter。而connector则是使用类似rpc的方式来访问agent,在agent端和客户端都必须有这样一个对象来处理相应的请求与应答。比如rmi connector。
jmx agent可以带有任意多个adapter,因此可以使用多种不同的方式访问agent。
jmx中的三层结构:
instrumentation 层:instrumentation层主要包括了一系列的接口定义和描述如何开发mbean的规范。通常jmx所管理的资源有一个或多个mbean组成,因此这个资源可以是任何由java语言开发的组件,或是一个javawrapper包装的其他语言开发的资源。
agent 层:agent用来管理相应的资源,并且为远端用户提供访问的接口。agent层构建在intrumentation层之上,并且使用并管理instrumentation层内部描述的组件。通常agent由一个mbeanserver和多个系统服务组成。另外agent还提供一个或多个adapter或connector以供外界的访问。
jmx agent并不关心它所管理的资源是什么。
distributed 层:distributed层关心agent如何被远端用户访问的细节。它定义了一系列用来访问agent的接口和组件,包括adapter和connector的描述。
- 一个java进程里面可以有多个不同名字的mbeanserver ,每个mbs都是一个独立的容器,用了管理mbean
- 每个mbs都可以注册多个rmi port,http port等
- platformmbeanserver 是由jvm创建的,并添加了一些系统的mbean,如cpu,内存,网络,线程等等
mbean代码示例
一个mbean是一个被管理的java对象,有点类似于javabean,一个设备、一个应用或者任何资源都可以被表示为mbean,mbean会暴露一个接口对外,这个接口可以读取或者写入一些对象中的属性,通常一个mbean需要定义一个接口,以mbean结尾, 例如: echombean, 格式为xxxmbean,这个是规范,必须得遵守。
import javax.management.mbeanserver; import javax.management.objectname; import java.lang.management.managementfactory; public class app { public static void main(string[] args) throws exception { // 创建mbeanserver mbeanserver mbs = managementfactory.getplatformmbeanserver(); // 新建mbean objectname, 在mbeanserver里标识注册的mbean objectname name = new objectname("com.csx.demo.spring.boot.jmx.mbean:type=echo"); // 创建mbean,echo类需要实现相关接口 echo mbean = new echo(); //注册以后可以通过jconsole等工具查看 // 在mbeanserver里注册mbean, 标识为objectname(com.dxz.mbean:type=echo) mbs.registermbean(mbean, name); // 在mbeanserver里调用已注册的echombean的print方法 mbs.invoke(name, "print", new object[] { "china sf"}, new string[] {"java.lang.string"}); thread.sleep(long.max_value); } }
通过上面代码发布echo后,我们就可以通过jconsole等工具查看echo在jmx上的注册情况了。
mbean本地连接
当我们启动java进程后,经常会使用jps,jinfo,jmap,jstat等jdk自带的命令去查询进程的状态,这其中的原理就是,当java进程启动后,会创建一个用于本机连接的“localconnectoraddress”放到当前用户目录下,当使用jps等连接时,会到当前用户目录下取到“localconnectoraddress”这个jmx连接地址并连接。
mbean远程连接
若想远程连接访问,肯定需要mbeanserver注册一个或多个端口,如rmi端口,http端口等。有两种方法可以配置远程连接:
一种是直接在代码里面指定rmi端口,并绑定,此种方法需要使用客户端代码访问,
另一种代码不用指定端口,只需要把mbean注册到platformmbeanserver 里面,并在启动进程时加jmx参数指定,用这种方法可以通过jconsole,jvisualvm远程访问。比如tomcat的监控配置
-dcom.sun.management.jmxremote=true 相关 jmx 代理侦听开关 -djava.rmi.server.hostname 服务器端的ip -dcom.sun.management.jmxremote.port=29094 相关 jmx 代理侦听请求的端口 -dcom.sun.management.jmxremote.ssl=false 指定是否使用 ssl 通讯 -dcom.sun.management.jmxremote.authenticate=false 指定是否需要密码验证
通过spring发布mbean
一些概念:
mbeanexporter: 从字面上很容易理解, 用来将一些spring的bean作为mbean暴露给mbeanserver。
mbeanserverfactorybean: 也可以在spring中作为一个spring bean注入, 它用来将外部或者当前机器上的mbeanserver包装成一个bean。
mbeaninfoassembler : 用来控制作为mbean的spring bean的哪些属性或方法将暴露出去, 以及决定何种形式的bean会被暴露成mbean. 不同的实现有不同的暴露方式。
objectnamingstrategy : 用来控制作为mbean暴露出去的spring bean在mbeanserver中将如何命名(objectname), 描述, 指定初始值等, objectname通常采用"域:键=值,键=值,...".
connectorserverfactorybean : 用来给外界访问当前spring中的mbeanserver bean提供一个连接器, 也就是给mbeanserver开一个外加访问的口子, 比如"service:jmx:jmxmp://localhost:9875" 让外界通过jmxmp协议, 通过9875端口来访问mbeanserver, 外界要访问mbeanserver, 必须提供一个connector. 默认连接器是jmxmp协议service:jmx:jmxmp://localhost:9875 , 也可以通过其他协议的连接器, 比如协议rmi,iiop, burlap,hessian,soap
mbeanserverconnectionfactorybean: 用来创建一个访问mbeanserver的客户端连接器, 比如mbeanserver bean暴露了一个服务器端连接器, 那么客户端就可以通过这个连接器来访问mbeanserver中的mbean. 可以理解为connectorserverfactorybean的对应物, server与client之间就是这两种连接器建立通讯连接
mbeanproxyfactorybean: 用来创建客户端访问远程mbeanserver中的mbean的代理, 客户端要访问服务器端的bean, 除了客户端连接器之外, 还需要一个代理, 相当于一个服务器端的stub.
//将spittlecontroller导出为mbean @managedresource(objectname="spitter:name=spittlecontroller3") public class spittlecntroller3 { // 默认每个页面的大小 public static final int default_spittles_per_page = 25; // 每页的大小 private int spittlesperpage = default_spittles_per_page; //@managedoperation@managedoperation注解替换@managedattribute注解来标注存取器方法 @managedattribute //将spittlesperpage暴露为托管属性 public int getspittlesperpage() { return spittlesperpage; } //@managedoperation@managedoperation注解替换@managedattribute注解来标注存取器方法 @managedattribute //将spittlesperpage暴露为托管属性 public void setspittlesperpage(int spittlesperpage) { this.spittlesperpage = spittlesperpage; } @requestmapping(value = "/test3", method = get) public string test() { string result = spittlesperpage + " - test()"; system.out.println(result); return "home"; } }
@managedresource将类暴露成mbean,@managedattribute暴露属相,@managedoperation暴露方法。上面的配置需要开启@enablembeanexport注解。
远程mbean的暴露和访问方法请参考
消息订阅发布
另外jmx还有消息发布和订阅功能。需要使用时可以参考。
参考
https://www.cnblogs.com/duanxz/category/689081.html
http://www.cnblogs.com/dongguacai/p/5900507.html
https://www.imooc.com/article/37008?block_id=tuijian_wz
https://blog.csdn.net/lmy86263/article/details/71037316