JMX的使用

news2025/1/11 21:54:09

1. 定义和意义 

JMX是Java Management Extention的缩写,出发点是让外部通过属性/方法来读取或设置程序状态。对于提供对外服务的程序来说,天生就有这样的能力,Web程序通过HTTP接口对外暴露,RPC应用通过RPC接口暴露。不过带来的问题,一是依赖环境,不同的环境能力不同;二是需要单独处理安全性问题,尤其是对公网暴露的情况下。JMX从某种程度上来说,解决了上述两个问题,无论什么应用都能通过JMX对外暴露管理功能,单独的非业务含义的协议和通道,可以避免非必要的公网暴露。

2. 架构 

JDK官网上介绍,JMX在架构上分为3层: Instrumentation、JMX Agent、Remote Management

2.1 Instrumentation 

Instrumentation定义了MBean的创建规范,JDK自带一组叫做MXBean的特殊MBean,对外提供JVM信息及操作。

2.2 JMX Agent

JMX Agent用来管理Instrument,核心是MBeanServer(用来注册MBean),并至少提供一组adaptor和connector,可以理解为通信协议和通信方式,允许外部程序或者客户端和JMX Agent通信。

2.3 Remote Management

可以把它理解为JMX Agent的客户端,通过不同的adapter和connect(协议和通信方式)连接到JMX Agent,进行远程调用。

3. 服务端

3.1 注册MBean
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
String domain = "MyMBean";
// 注册hello
ObjectName helloName = new ObjectName(domain + ":name=hello");
server.registerMBean(new Hello(),helloName);
3.2 启动服务
  1. 使用JVM参数
-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=1099 
-Dcom.sun.management.jmxremote.local.only=false 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false
  1. 使用Java代码
String domain = "jmxrmi"
int rmiPort = 1099;
Registry registry = LocateRegistry.createRegistry(rmiPort);
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + rmiPort + "/" + domain);
JMXConnectorServer jmxConnector = JMXConnectorServerFactory.newJMXConnectorServer(url,null,server);
jmxConnector.start();

如果是代码或者是远程连接JMX Agent,后续会用到JMXServiceURL的地址。和使用Java代码创建不同,JVM参数的domain值固定为jmxrm

4. 客户端

JMX的客户端有两类,一类是现成的GUI工具,如JConsole、VisualVM等;另一类是通过代码操作。通过GUI程序启动的客户端,只需要直接选择对应进程ID,或者填入注册MBean时提供的JMXServiceURL即可,如下图所示。这里我们主要聚焦通过代码操作MBean。

4.1 建立连接

和启动JMXConnectorServer一样,先建立JMXServiceURL,不同的是这里创建的是JMXConnector对象。

String domain = "jmxrmi";
int rmiPort = 1099;
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + rmiPort + "/" + domain);
JMXConnector jmxc = JMXConnectorFactory.connect(url);
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
4.2 MBean列表
Set<ObjectInstance> ins = mbsc.queryMBeans(null,null);
for(ObjectInstance i : ins) {    
    System.out.println("object: " + i.getObjectName());
}
4.3 Domain列表
String[] domains = mbsc.getDomains();
for (String d : domains) {    
    System.out.println(d);
}
4.4 MBean计数
System.out.println("MBeanCount:" + mbsc.getMBeanCount());
4.5 属性读写
String domain = "MyMBean";
ObjectName helloName = new ObjectName(domain + ":name=hello");
System.out.println("getAttribute:--->" + mbsc.getAttribute(helloName, "Slogan")); // 获取
mbsc.setAttribute(helloName, new Attribute("Slogan", "" + System.nanoTime())); // 设置
System.out.println("getAttribute modified--->" + mbsc.getAttribute(helloName, "Slogan")); // 获取
4.6 方法调用

有两种方式可以调用MBean的方法,一种是直接使用MBeanServerConnection调用

String domain = "MyMBean";
ObjectName helloName = new ObjectName(domain + ":name=hello");
 // 无返回
mbsc.invoke(helloName, "printHello", new String[]{"shit"}, new String[]{String.class.getName()});
 // 有返回
Object resp = mbsc.invoke(helloName, "daydream", new Integer[]{5000}, new String[]{Integer.class.getName()});
System.out.println("daydream:--->" + resp);

还有一种方式是通过BeanServerInvocationHandler生成代理对象,再用这个对象直接调用

String domain = "MyMBean";
ObjectName helloName = new ObjectName(domain + ":name=hello");
HelloMBean proxy = MBeanServerInvocationHandler.newProxyInstance(mbsc,helloName,HelloMBean.class,false);
System.out.println("proxy get attribute:" + proxy.getSlogan());
System.out.println("proxy invoke:" + proxy.daydream(9999));

第二种方式的使用体验会好一些,尤其是需要频繁、多次使用MBean的方法时。

4.7 BeanInfo读写
String domain = "MyMBean";
ObjectName helloName = new ObjectName(domain + ":name=hello");

MBeanInfo beanInfo = mbsc.getMBeanInfo(helloName);
System.out.println("class name:" + beanInfo.getClassName()); // MBean实现类

MBeanAttributeInfo[] attrinfos = beanInfo.getAttributes();  // MBean的属性
for(MBeanAttributeInfo a: attrinfos) {
    System.out.println("attribute name:" + a.getName());
}

MBeanOperationInfo[] operationInfos = beanInfo.getOperations(); // MBean上的操作
for(MBeanOperationInfo o: operationInfos) {
    System.out.println("operation name:" + o.getName());
}

5. Spring对JMX的支持

5.1 MBeanServer

通过提供MBeanServerFactoryBean,允许我们声明配置并创建MBeanServer对象

@Bean
public MBeanServerFactoryBean mbeanServer() {
    MBeanServerFactoryBean mbeanServer = new MBeanServerFactoryBean();
    return mbeanServer;
}
5.2 JMXConnectorServer

提供了ConnectorServerFactoryBean对象,用于配置并创建JMXConnectorServer

@Bean
public ConnectorServerFactoryBean connectorServer() {
    ConnectorServerFactoryBean factoryBean = new ConnectorServerFactoryBean();
    factoryBean.setServer(mbeanServer().getObject());
    factoryBean.setServiceUrl("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi");
    return factoryBean;
}
5.3 注册MBean

要启用对MBean的自动注册,如果是Spring Boot应用的话,在@Configuration类上添加一个注解@EnableMBeanExport,注册MBean有两种方案可选,一种方式是使用MBeanExporter,可以用正常的Spring Bean配置为MBean,比如这里的globalProduct bean,后面被做为MBean的目标对象。

@Bean
public Product globalProduct() {
    Product product = new Product();
    product.setId(1234L);
    product.setStaticScore(1.222F);
    product.setRelationScore(2.333F);
    product.setCategoryId(4321);
    return product;
}

@Bean
public MBeanExporter hello() {
    MBeanExporter exporter = new MBeanExporter();
    Map<String, Object> beans = new HashMap<>();
    beans.put("hello:name=globalProduct", globalProduct());
    exporter.setBeans(beans);
    exporter.setServer(mbeanServer().getObject());
    return exporter;
}

另一种方案是通过注解,使用@ManagedResource、@ManagedAttribute、@ManagedOperation注解,直接暴露Bean对象

@Component
@ManagedResource(objectName = "hello:name=appInfo")
public class AppInfo {

    @ManagedAttribute(description = "numbers of processors")
    public int getProcessorCount() {
        return Runtime.getRuntime().availableProcessors();
    }

    @ManagedOperation
    public void resetSystemProperties() {
        System.getProperties().setProperty("appInfo","lws");
    }
}

6. 效果和评估

通过JConsole连接到我们的应用,查看MBean效果如下图。除了我们自己注册的MBean,Java默认提供一对内置MBean,用来读取系统、JVM的信息,包括类加载、内存使用、GC、ClassPath、环境变量等等信息,甚至可以通过JFR的MBean来启动JFR记录,打线程堆栈、手工执行GC等等。

单纯的从Java用户的角度来说,这不失为一种不错的Java管理的扩展能力(Java Management Extension),有一定的基础设施,使用也算方便。但是在跨语言方法就显得有点弱势,网上也可以看到各种从JMX适配到其他协议的工具,以便将JMX数据暴露给其他中间件,比如Promethus和JMX 之间就有个JMX Exporter,让Promethus能获取JMX的数据。

经过上面的学习和试验后,我们对JMX态度是可以了解和使用,不必要过多深入,学完本文的内容已经够用。有具体使用场景,比如希望通过JMX监控Kafka,再详细了解Kafka提供的MBean即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1276343.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何快速选出一支好股票?

俗话说得好&#xff1a;股票选得好&#xff0c;收益少不了&#xff01;不用多说&#xff0c;相信大伙儿都知道选一支好股票究竟有多重要。 但是选股可不像咱们去菜市场买菜一样&#xff0c;看着顺眼就成。选股&#xff0c;其实是一个专业性特别强的技术活儿。 目前最常用的选股…

微信开发者工具真机调试连接状态在正常和未连接之间反复横跳

开启局域网模式能解决这个问题&#xff0c;目前只找到这一个方法

详解Linux常用命令

目录 1. ps 命令 2. top 命令 3. grep 命令 4. df 命令 5. tail 命令 6. head 命令 7. cat 命令 8. --help 和 man 命令 9. cd 命令 10. mkdir 命令 11. rm 命令 12. mv 和 cp 命令 13. touch 命令 14. vi 或 vim 命令 15. chmod 修改权限 16. 打包和压缩文件 …

电子学会C/C++编程等级考试2021年12月(四级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:移动路线 桌子上有一个m行n列的方格矩阵,将每个方格用坐标表示,行坐标从下到上依次递增,列坐标从左至右依次递增,左下角方格的坐标为(1,1),则右上角方格的坐标为(m,n)。 小明是个调皮的孩子,一天他捉来一只蚂蚁,不小心把…

Windows的常用cmd命令总结

文章目录 一.盘符切换二: cd命令(打开文件/文件夹)三:查看目录四.创建和删除文件夹五.查看本机ip地址六.清除当前屏幕七.复制文件到另一个地方八.移动文件到另一个地方九.删除文件&#xff08;不能删除文件夹&#xff09;十.测试网络连接十一.停止任务进程Windows快捷键总结大全…

python简单进阶之web框架:fastapi使用教程

原文&#xff1a;python简单进阶之web框架&#xff1a;fastapi使用教程 - 知乎 这是简单进阶教程系列第四篇&#xff0c;本系列文章主要介绍那些可以很快上手的进阶库。 我其实学过一段时间Django框架&#xff0c;但是半途而废了&#xff0c;我觉得可能还是简单一点的框架比较适…

瑜伽学习零基础入门,各种瑜伽教学方法全集

一、教程描述 练习瑜伽的好处多多&#xff0c;能够保证平衡健康的身体基础&#xff0c;提升气质、塑造形体、陶冶情操&#xff0c;等等。本套教程是瑜伽的组合教程&#xff0c;共由33套视频教程组合而成&#xff0c;包含了塑身纤体&#xff0c;速效瘦身&#xff0c;四季养生&a…

csp 现值计算 C语言

号&#xff1a; 202212-1 试题名称&#xff1a; 现值计算 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 512.0MB 问题描述&#xff1a; 问题描述 评估一个长期项目的投资收益&#xff0c;资金的时间价值是一个必须要考虑到的因素。简单来说&#xff0c;假设…

010 数据结构_红黑树

前言 本文将会向你介绍红黑树的概念、性质&#xff0c;以及如何手撕红黑树 1 文章重点 文本首先引入红黑树的概念和性质&#xff0c;性质非常重要对于后面的插入操作来说&#xff0c;文章的核心放在了插入部分&#xff0c;另外看插入部分之前记得看声名和节点的定义哦~ 2 引…

HarmonyOs 4 (二) HelloWord

目录 一 开发工具下载安装1.1 下载安装包1.2 下载相关依赖 二 开发者注册与个人实名认证三 第一个程序2.1 创建第一个程序2.2 认识开发者界面2.3 目录结构认识2.3.1 父目录认识2.3.2 AppScope 目录2.3.3 entry目录2.3.3.1 ets 目录2.3.3.2 resources目录 2.3.4 认识配置文件2.3…

leetCode 90.子集 II + 回溯算法 + 图解 + 笔记

给你一个整数数组 nums &#xff0c;其中可能包含重复元素&#xff0c;请你返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。返回的解集中&#xff0c;子集可以按 任意顺序 排列 示例 1&#xff1a; 输入&#xff1a;nums [1,2,2] 输出…

k8s报错

报错&#xff1a; 这个错误信息表明你的容器运行时&#xff08;container runtime&#xff09;没有正常运行&#xff0c;具体是因为CRI&#xff08;容器运行时接口&#xff09;v1版本的API没有为特定的端点实现。这通常发生在使用containerd作为容器运行时时。错误信息中提到的…

Java集合(二)

1. Map 1.1 HashMap 和 Hashtable 的区别 线程是否安全&#xff1a; HashMap 是非线程安全的&#xff0c;Hashtable 是线程安全的,因为 Hashtable 内部的方法基本都经过synchronized 修饰。&#xff08;如果你要保证线程安全的话就使用 ConcurrentHashMap 吧&#xff01;&…

生物教师个人简历(精选21篇)

以下21篇简历内容以生物教师招聘需求为背景制作&#xff0c;大家可以灵活借鉴&#xff0c;希望能帮助大家在众多候选人中脱颖而出。 生物教师个人简历下载&#xff08;在线制作&#xff09;&#xff1a;百度幻主简历或huanzhuv.com 生物老师简历1&#xff1a; 求职意向 求职…

手机文件怎么传到电脑?简单方法分享!

将手机文件传输到电脑可以将其备份&#xff0c;以防数据丢失或意外情况发生。并且电脑具有更强大的处理能力&#xff0c;可以将文件进行编辑、修改、转换等操作&#xff0c;大大提高了工作效率。那么&#xff0c;手机文件怎么传到电脑&#xff1f;本文将为大家提供简单易懂的解…

nodejs微信小程序+python+PHP学科建设管理信息系统的设计与实现-计算机毕业设计推荐

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

【二分查找】LeetCode1970:你能穿过矩阵的最后一天

本文涉及的基础知识点 二分查找算法合集 作者推荐 动态规划LeetCode2552&#xff1a;优化了6版的1324模式 题目 给你一个下标从 1 开始的二进制矩阵&#xff0c;其中 0 表示陆地&#xff0c;1 表示水域。同时给你 row 和 col 分别表示矩阵中行和列的数目。 一开始在第 0 …

Python基础学习快速入门

文章目录 Number变量String字符串Def函数Class类List列表Tuple元组Dictionary字典Set集合值与引用类型if条件控制Loop循环 Number变量 python直接赋值&#xff0c;不需要定义变量类型。不需要**,逗号结尾符 使用print**直接进行输出 #赋值 a 1.0 print(a)a 7 print(a)p…

C语言错误处理之 “<errno.h>与<error.h>”

目录 前言 错误号处理方式 errno.h头文件 error.h头文件 参数解释&#xff1a; 关于的”__attribute__“解释&#xff1a; 关于“属性”的解释&#xff1a; 实例一&#xff1a; 实例二&#xff1a; error.h与errno.h的区别 补充内容&#xff1a; 前言 在开始学习…

[论文精读]利用大语言模型对扩散模型进行自我修正

本博客是一篇最新论文的精读&#xff0c;论文为UC伯克利大学相关研究者新近(2023.11.27)在arxiv上上传的《Self-correcting LLM-controlled Diffusion Models》 。 内容提要: 现有的基于扩散的文本到图像生成模型在生成与复杂提示精确对齐的图像时仍然存在困难,尤其是需要数值和…