JMX的使用

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();}@ManagedOperationpublic 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.mzph.cn/news/188474.shtml

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

相关文章

ESP32-Web-Server编程- 使用表格(Table)实时显示设备信息

ESP32-Web-Server编程- 使用表格&#xff08;Table&#xff09;实时显示设备信息 概述 上节讲述了通过 Server-Sent Events&#xff08;以下简称 SSE&#xff09; 实现在网页实时更新 ESP32 Web 服务器的传感器数据。 本节书接上会&#xff0c;继续使用 SSE 机制在网页实时显…

深度学习手势识别 - yolo python opencv cnn 机器视觉 计算机竞赛

文章目录 0 前言1 课题背景2 卷积神经网络2.1卷积层2.2 池化层2.3 激活函数2.4 全连接层2.5 使用tensorflow中keras模块实现卷积神经网络 3 YOLOV53.1 网络架构图3.2 输入端3.3 基准网络3.4 Neck网络3.5 Head输出层 4 数据集准备4.1 数据标注简介4.2 数据保存 5 模型训练5.1 修…

C++模板—函数模板、类模板

目录 一、函数模板 1、概念 2、格式 3、实例化 4、模板参数的匹配 二、类模板 1、定义格式 2、实例化 交换两个变量的值&#xff0c;针对不同类型&#xff0c;我们可以使用函数重载实现。 void Swap(double& left, double& right) {double tmp left;left ri…

黑马一站制造数仓实战1

1. 项目目标 一站制造 企业中项目开发的落地&#xff1a;代码开发 代码开发&#xff1a;SQL【DSL SQL】 SparkCore SparkSQL 数仓的一些实际应用&#xff1a;分层体系、建模实现 2. 内容目标 项目业务介绍&#xff1a;背景、需求 项目技术架构&#xff1a;选型、架构 项目环境…

SpringBootWeb案例_03

Web后端开发_06 SpringBootWeb案例_03 登录认证 智能学习辅助系统登录时需要身份验证 1.登录功能 先实现简单的登录功能&#xff0c;在进一步优化。 1.1需求 若账户或密码不存在/密码不正确&#xff0c;则登录失败。 账户密码正确&#xff0c;则登录成功 1.2接口文档 …

git基本概念

一、版本控制概念 1.1 什么是版本控制 1.1.1 手动管理文件版本 1.1.2 版本控制软件 概念&#xff1a;版本控制软件是一个用来记录文件发生的变化&#xff0c;以便将来查阅特定版本修订情况的系统&#xff0c;有时也叫“版本控制系统”。通俗的理解就是把手工管理文件版本的方…

关于电脑提示vcruntime140_1.dll无法继续执行代码的解决办法

vcruntime140_1.dll是Visual C运行时库的一个组成部分&#xff0c;它包含了大量用于支持C应用程序运行时的功能。这个文件通常在开发和使用C程序时被调用&#xff0c;特别是在使用Microsoft Visual Studio进行开发时。vcruntime140_1.dll文件丢失或损坏会导致C程序无法正常运行…

信息化,数字化,智能化是3种不同概念吗?与机械化,自动化矛盾吗?

先说结论&#xff1a; 1、信息化、数字化、智能化确实是3种不同的概念&#xff01; 2、这3种概念与机械化、自动化并不矛盾&#xff0c;它们是制造业中不同发展阶段和不同层次的概念。 机械化&#xff1a;是指在生产过程中使用机械技术来辅助人工完成一些重复性、单一性、劳…

助力android面试2024【面试题合集】

转眼间&#xff0c;2023年快过完了。今年作为口罩开放的第一年大家的日子都过的十分艰难&#xff0c;那么想必找工作也不好找&#xff0c;在我们android开发这一行业非常的卷&#xff0c;在各行各业中尤为突出。android虽然不好过&#xff0c;但不能不吃饭吧。卷归卷但是还得干…

Pytorch——多卡GPU训练与单卡GPU训练相互切换

部分深度学习网络默认是多卡并行训练的&#xff0c;由于某些原因&#xff0c;有时需要指定在某单卡上训练&#xff0c;最近遇到一个&#xff0c;这里总结如下。 目录 一、多卡训练1.1 修改配置文件1.2 修改主训练文件1.3 显卡使用情况 二、单卡训练2.1 修改配置文件2.2 显卡使…

简单了解下IP的全球划分【笔记】

国际互联网号码分配机构 (The Internet Assigned Numbers Authority&#xff0c;简称IANA&#xff09;。它是互联网名称与数字地址分配机构&#xff08;The Internet Corporation for Assigned Names and Numbers&#xff0c;简称ICANN&#xff09;旗下的一个机构&#xff0c;主…

Linux5-计划任务、进程

计划任务 一、cron 计划任务 周期性计划任务 cron 任务概述 • 用途:按照设置的时间间隔为用户反复执行某一项固定的系统任务 • 软件包&#xff1a;cronie、crontabs • 系统服务&#xff1a;crond • 日志文件&#xff1a;/var/log/crond 管理计划任务策略 • 使用 cro…

存储虚拟化的写入过程

存储虚拟化的场景下&#xff0c;整个写入的过程。 在虚拟机里面&#xff0c;应用层调用 write 系统调用写入文件。write 系统调用进入虚拟机里面的内核&#xff0c;经过 VFS&#xff0c;通用块设备层&#xff0c;I/O 调度层&#xff0c;到达块设备驱动。虚拟机里面的块设备驱动…

uniapp uni-popup组件在微信小程序中滚动穿透问题

起因 在微信小程序中使用uni-popup组件时&#xff0c;出现滚动穿透&#xff0c;并且uni-popup内部内容不会滚动问题。 解决 滚动穿透 查阅官方文档&#xff0c;发现滚动穿透是由于平台差异性造成的&#xff0c;具体解决可以参照文档禁止滚动穿透 <template><page-…

【概率统计】如何理解概率密度函数及核密度估计

文章目录 概念回顾浅析概率密度函数概率值为0&#xff1f;PDF值大于1&#xff1f;一个栗子 核密度估计如何理解核密度估计核密度估计的应用 总结 概念回顾 直方图&#xff08;Histogram&#xff09;&#xff1a;直方图是最直观的一种方法&#xff0c;它通过把数据划分为若干个区…

软件工程 - 第8章 面向对象建模 - 2 静态建模

静态建模&#xff08;类和对象建模&#xff09; 类和对象模型的基本模型元素有类、对象以及它们之间的关系。系统中的类和对象模型描述了系统的静态结构&#xff0c;在UML中用类图和对象图来表示。 类图由系统中使用的类以及它们之间的关系组成。类之间的关系有关联、依赖、泛…

Numpy进阶

NumPy进阶80题完整版

卓扬网林荣雄说:开盘30分钟便能看清股票的涨跌

在一些人眼中&#xff0c;炒股是一件再简单不过的事情了&#xff0c;他们认为只需要简单地买进卖出&#xff0c;就可以玩转股票了。话虽如此&#xff0c;但是要想真正立足于股市&#xff0c;简单的买进卖出是远远不够的。要想长期屹立于股市之中&#xff0c;广大股民还需要积累…

Adobe ColdFusion文件读取漏洞(CVE-2010-2861)

任务一&#xff1a; 复现漏洞 任务二&#xff1a; 尝试利用漏洞读取目标系统中的“opt/coldfusion8/license.txt"文件 1.环境搭建&#xff08;网上写的密码是admin&#xff0c;就用admin&#xff09; 2.看答案就是一层一层进行路径穿越攻击&#xff0c;这里要注意如果…

【动态规划】LeetCode-63.不同路径II

&#x1f388;算法那些事专栏说明&#xff1a;这是一个记录刷题日常的专栏&#xff0c;每个文章标题前都会写明这道题使用的算法。专栏每日计划至少更新1道题目&#xff0c;在这立下Flag&#x1f6a9; &#x1f3e0;个人主页&#xff1a;Jammingpro &#x1f4d5;专栏链接&…