JMX的全称为Java Management Extensions. 顾名思义,是管理Java的一种扩展。这种机制可以方便的管理正在运行中的Java程序。常用于管理线程,内存,日志Level,服务重启,系统环境等。
JMX的架构图如下:
从上面的架构图可以看到JMX主要分三层,分别是:
1、设备层(Instrumentation Level)
主要定义了信息模型。在JMX中,各种管理对象以管理构件的形式存在,需要管理时,向MBean服务器进行注册。该层还定义了通知机制以及一些辅助元数据类。
设备层其实就是和被管设备通信的模块,对于上层的管理者来说,Instrumentation 就是设备,具体设备如何通信,是采用SNMP,还是采用ICMP,是MBean的事情。
该层定义了如何实现JMX管理资源的规范。一个JMX管理资源可以是一个Java应用、一个服务或一个设备,它们可以用Java开发,或者至少能用Java进行包装,并且能被置入JMX框架中,从而成为JMX的一个管理构件(Managed Bean),简称MBean。管理构件可以是标准的,也可以是动态的,标准的管理构件遵从JavaBeans构件的设计模式;动态的管理构件遵从特定的接口,提供了更大的灵活性。
在JMX规范中,管理构件定义如下:它是一个能代表管理资源的Java对象,遵从一定的设计模式,还需实现该规范定义的特定的接口。该定义了保证了所有的管理构件以一种标准的方式来表示被管理资源。
管理接口就是被管理资源暴露出的一些信息,通过对这些信息的修改就能控制被管理资源。一个管理构件的管理接口包括:
本文着重介绍最基本也是用的最多的Standard Mbean,至于其它的如Dynamic MBean、Model MBean暂时不介绍,请参考本文最后资料中的文章。
Standard MBean是最简单的MBean,它管理的资源必须定义在接口中,然后MBean必须实现这个接口。它的命名也必须遵循一定的规范,例如我们的MBean为Hello,则接口必须为HelloMBean。
2、代理层(Agent Level)
Agent层 用来管理相应的资源,并且为远端用户提供访问的接口。Agent层构建在设备层之上,并且使用并管理设备层内部描述的组件。Agent层主要定义了各种服务以及通信模型。该层的核心是 MBeanServer,所有的MBean都要向它注册,才能被管理。注册在MBeanServer上的MBean并不直接和远程应用程序进行通信,他们通过 协议适配器(Adapter) 和 连接器(Connector) 进行通信。通常Agent由一个MBeanServer和多个系统服务组成。JMX Agent并不关心它所管理的资源是什么。
3、分布服务层(Distributed Service Level)
分布服务层关心Agent如何被远端用户访问的细节。它定义了一系列用来访问Agent的接口和组件,包括Adapter和Connector的描述。
Standard MBean的设计和实现是最简单的,它们的管理接口通过方法名来描述。Standard MBean的实现依靠一组命名规则。这些命名规则定义了属性和操作。
一个只读属性在MBean中只有get方法,既有get又有set方法表示是一个可读写的属性。
为了实现Standard MBean,必须遵循一套继承规范。必须为每一个MBean定义一个接口,而且这个接口的名字必须是其被管理的资源的对象类的名称后面加上”MBean”,之后把它们注册到MBeanServer中就可以了。
详细可参考文章:https://www.cnblogs.com/trust-freedom/p/6842332.html
1、首先新建一个SpringBoot工程,并生成类似如下的启动类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2、编写暴露的MBean
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@Component
@ManagedResource(objectName = "com.tang.jmx:type=SimpleBean", description = "这里是描述")
public class SimpleBean {
private long id;
private String name;
private int age;
public void setId(long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
/**
* 这里编写暴露方法
*/
@ManagedOperation(description = "这里是操作")
public String display() {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writeValueAsString(this);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}
3、编写一个外部调用接口,用来低5步模拟内存数据发生变化
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class JmxController {
@Autowired
private SimpleBean simpleBean;
@GetMapping("/jmx")
public SimpleBean simpleBean(@RequestParam(required = true) Long id,
@RequestParam(required = true) String name,
@RequestParam(required = true) Integer age
){
simpleBean.setId(id);
simpleBean.setName(name);
simpleBean.setAge(age);
return simpleBean;
}
}
4、在application.properties配置文件中配置开启jmx
spring.jmx.enabled=true
5、启动程序,并以GET请求调用接口:
http://127.0.0.1:8080/jmx?id=1&name=xxx&age=22
6、启动VisualVM工具,并attach到上述进程中,并找到MBeans属性页,查看jmx暴露的监控bean信息:
参考文章:
(1) https://www.cnblogs.com/trust-freedom/p/6842332.html
(2) https://www.cnblogs.com/yangzhilong/p/10794795.html
(3) https://segmentfault.com/a/1190000015355526
(4) https://www.cnblogs.com/dongguacai/p/5900507.html