JMX

JMX的全称为Java Management Extensions. 顾名思义,是管理Java的一种扩展。这种机制可以方便的管理、监控正在运行中的Java程序。常用于管理线程,内存,日志Level,服务重启,系统环境等

基本术语

  • 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。

Spring JMX

为了将一个POJO变为MBean,一个做法是定义一个XXXXMBean为名的接口,然后实现它。

而Spring提供了一种更简单的方法,Annotation注释即可,既可以将POJO变为MBean,还可以为属性,方法及其参数都加上描述,为JConsole进行操作时提供更好的帮助信息。

  • @ManagedResource 在类上使用,把类标记为MBean。
  • @ManagedOperation 在可操作的方法加使用。
  • @ManagedAttribute 在字段上使用。如果属性是可读可写的,就在getter和setter上都注释,只读的话就只在getter上注释。
package com.example.demo.jmx;

import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.stereotype.Component; import java.util.concurrent.atomic.AtomicLong;
@Component
@ManagedResource(objectName="test.jmx:name=ServerManager",
description="Server manager.")
public class Hello { private final AtomicLong alarm = new AtomicLong(0); @ManagedAttribute
public Integer getAlarm() {
return alarm.intValue();
} @ManagedOperation
public void setAlarm() {
alarm.incrementAndGet();
}
}

新建一个SpringBoot项目,添加像上面使用注解的类,启动项目后,就可以在JConsole查看MBean的情况了。

支持JMX远程连接

如果是用Jolokia将JMX Restful JSON的话,远程连接就不是必须的。如果仍然要远程连接,可以在启动JVM时加上系统参数

-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.port=3099

JConsole

如果JConsole与应用在同一台机器,直接选择该进程

远程进程URL可以简单的写host:portlocalhost:2099

练打字的话写完整版的service:jmx:rmi:///jndi/rmi://localhost:2099/jmxrmi

自定义MBean(非Spring方式)

  1. 新建接口
package com.example.demo.jmx;

public interface AlarmMBean {
Integer getAlarm();
void setAlarm();
}
  1. 新建实现类
package com.example.demo.jmx;
import java.util.concurrent.atomic.AtomicLong; public class Alarm implements AlarmMBean{ private final AtomicLong alarm = new AtomicLong(0); @Override
public Integer getAlarm() {
return alarm.intValue();
} @Override
public void setAlarm() {
alarm.incrementAndGet();
}
}
  1. 注册MBean

    Demo程序在main访法中调用即可
    private static void registerMBean(String module,Integer errorCode) {
try {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("jmxBean:name="+module+"-"+errorCode);
//create mbean and register mbean
server.registerMBean(new Alarm(), name); } catch (Exception e) {
System.out.println(e);
}
}
  1. 支持JConsole远程连接
    private static void jmxConnect() {
try {
MBeanServer server = ManagementFactory.getPlatformMBeanServer(); LocateRegistry.createRegistry(9999);
//URL路径的结尾可以随意指定,但如果需要用Jconsole来进行连接,则必须使用jmxrmi
JMXServiceURL url = new JMXServiceURL
("service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi");
JMXConnectorServer jcs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);
System.out.println("begin rmi start");
jcs.start();
System.out.println("rmi start"); } catch (Exception e) {
System.out.println(e);
} }

这样就可以在JConsole中用localhost:9999连接。

prometheus jmx_exporter

通过HTTP公开JMX Bean以供Prometheus使用的过程

https://github.com/prometheus/jmx_exporter

配置文件config.yaml

---
lowercaseOutputLabelNames: true
lowercaseOutputName: true
#whitelistObjectNames: ["java.lang:type=OperatingSystem","jmxBean:type=custom",*]
#blacklistObjectNames: []
rules:
#在JConsole中可观察到自定义MBean:jmxBean:name=reactor-100102
- pattern: 'jmxBean<name=(\w+)-(\d+)><>(alarm):'
name: test_$1_$2
labels:
"module": "$1"
"errorCode": "$2"
type: COUNTER
attrNameSnakeCase: true

whitelistObjectNames 中配置MBean的白名单,缺省设置默认是全部公开的MBean。

()每个小括号的正则结果对应$1,$2...的变量。

更多的选项设置Github文档中有更详细描述和示例配置。

模式匹配格式 (pattern)

与模式匹配的输入格式为

domain<beanpropertyName1=beanPropertyValue1, beanpropertyName2=beanPropertyValue2, ...><key1, key2, ...>attrName: value
部分 描述
domain 定义ObjectName时,JMX对象名称中冒号之前的部分。
beanProperyName/Value Bean属性。这些是JMX对象名称中冒号后面的键/值。
key 如果遇到复合数据或表格数据,则将属性名称添加到此列表中。
attrName 属性的名称。对于表格数据,这将是列的名称
value 属性的值。

预设格式

在大多数情况下,缺省格式将以一种可以产生健全度量标准的方式转换bean。它是

domain_beanPropertyValue1_key1_key2_...keyN_attrName{beanpropertyName2="beanPropertyValue2", ...}: value

javaagent运行

要作为javaagent运行,请下载jar并运行:

java -javaagent:./jmx_prometheus_javaagent-0.12.0.jar=8081:config.yaml -jar yourJar.jar

现在可以在http://localhost:8081 上访问指标

要将Java代理绑定到特定IP,请将端口号更改为host:port。

JavaAgent.java

https://github.com/prometheus/jmx_exporter/blob/master/jmx_prometheus_javaagent/src/main/java/io/prometheus/jmx/JavaAgent.java

Prometheus和Grafana的配置这里不讲,可以找其它文章进行配置。

参考链接:

https://www.cnblogs.com/dongguacai/p/5900507.html

https://blog.csdn.net/u013256816/article/details/52800742

https://github.com/springside/springside4/wiki/Jmx

https://docs.spring.io/spring-boot/docs/2.1.9.RELEASE/reference/html/boot-features-jmx.html

https://github.com/prometheus/jmx_exporter

最新文章

  1. Boost信号/槽signals2
  2. 【Win 10应用开发】自定义浮动层——Flyout
  3. BackGroundWorker控件的使用注意
  4. java运行jar命令提示没有主清单属性
  5. 【转】HBase原理和设计
  6. Android的Proxy/Delegate Application框架 (主要介绍插件化开发)
  7. 心情闲适,发几个tatanic的图
  8. 常用jquery插件资料
  9. Mysql ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA
  10. shell随机写入指定文件
  11. div紧靠浏览器底部
  12. PostgreSQL的 initdb 源代码分析之九
  13. So many interfaces!
  14. 【转】Install SmartGit via PPA in Ubuntu 13.10/13.04/12.04/Linux Mint
  15. 如何 查看 WebLogic Server的版本号[转]
  16. robotium从入门到放弃 二 第一个实例
  17. Kubernetes Dashboard - 每天5分钟玩转 Docker 容器技术(173)
  18. 恢复git撤销commit的代码
  19. GraphQL 是什么
  20. Shell基本介绍和使用

热门文章

  1. 学习笔记之javascript编写简单计算器
  2. C++学习笔记4_new和delete
  3. [考试反思]1031csp-s模拟测试96:常态
  4. [考试反思]0922csp-s模拟测试50:谜朦
  5. 小白学 Python(18):基础文件操作
  6. Apache服务部署静态网站
  7. 大数据之路day02_1--运算符
  8. C语言程序设计100例之(4):水仙花数
  9. Http帮助类(史上最详细帮助类)
  10. Linux基于webRTC的二次开发(二) 实现远程桌面共享