Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说「进阶之路」揭开JMX的神秘面纱,希望能够帮助你!!!。
No.1 相关概念
JMX(Java Management Extensions)是一个为应用程序植入管理功能的框架。JMX是一套标准的代理和服务,实际上,用户可以在任何Java应用程序中使用这些代理和服务实现管理。
JMX 要管理的对象是什么呢,是资源。
什么是资源,资源是指企业中的的各种应用软件和平台,举例来说,一个公司内部可能有许多应用服务器、若干 Web 服务器、一台或多台的数据库服务器及文件服务器等等,
那么,如果我们想监视数据库服务器的内存使用情况,或者我们想更改应用服务器上 JDBC 最大连接池的数目,但我们又不想重启数据库和应用服务器,这就是典型意义上的资源管理,
即对我们的资源进行监视 (Monitoring ,查看 ) 和管理 (Management ,更改 ) ,这种监视和更改不妨碍当前资源的正常运行。
对资源进行适当的监测和管理,可以让我们的 IT 资源尽可能的平稳运行,可以为我们的客户提供真正意思上的 24 × 7 服务。
在资源耗尽或者在硬件出故障之前,我们就可以通过管理工具监测到,并通过管理工具进行热调整和插拔。
应用场景:中间件软件WebLogic的管理页面就是基于JMX开发的,而JBoss则整个系统都基于JMX构架。
No.2 JMX架构
JMX的结构一共分为三层:
2.1、基础层(MBean)
该层包含 MBeans 及这些 MBeans 所管理的资源, MBeans 是一个 Java 对象,它必须实现 JMX 规范中规定的接口。
按照 JMX 规范,在 MBeans 对象的接口中,我们可以指定管理层可以访问资源的哪些属性,可以调用资源的哪些方法,并且,在资源的属性发生变化时,我们的 MBeans 可以发出消息,通知对这些属性变化感兴趣的其它对象。
JMX 规范定义了四种 MBeans ,它们分别是标准 MBeans(Standard MBeans) 、动态 MBeans(Dynamic MBeans) 、开放 MBeans(Open MBeans) 和模态 MBeans(Model MBeans) 。
2.2、代理层(Agent)
代理层的目的就是要把 MBeans 中实现的接口暴露给管理层,该层通常由 MBean Server 和 Agent Services 构成。
2.3、管理层(Manager)
又称之为分布式服务层 (Distributed Services) ,顾名思义,该层主要包含一些管理应用程序,这些程序可以访问和操作 JMX 代理层 (Agent Level) 。
No.3 示例程序
3.1、需求
在企业内部应用中,假设我们需要对应用所使用的数据库进行动态的切换(现实中应该没有这样的需求,这里只是为了举例),而且在切换过程中应用不能暂停服务,即必须保证7*24小时的运行。
3.2、设计
一般情况下,系统在切换数据库时,需要对数据库配置信息进行修改,然后重启服务,加载新的数据库配置信息。但是我们这里不能这样做,因为不能暂停服务。
那我们就使用JMX技术来实现吧。
3.3、编码
package io.xiaojl.jmx;
/**
* <p>Title: DBConfigMBean</p>
*
* <p>Description: 数据库配置资源的接口类</p>
*
* @author jilong.xiao
* @date 2018年9月11日
*/
public interface DBConfigMBean {
String getDriverClass();
String getUrl();
String getUsername();
String getPassword();
void setDriverClass(String driverClass);
void setUrl(String url);
void setUsername(String username);
void setPassword(String password);
}
package io.xiaojl.jmx;
/**
* <p>Title: DBConfig</p>
*
* <p>Description: MBean(资源)</p>
*
* @author jilong.xiao
* @date 2018年9月11日
*/
public class DBConfig implements DBConfigMBean {
private String driverClass;
private String url;
private String username;
private String password;
@Override
public String getDriverClass() {
return this.driverClass;
}
@Override
public String getUrl() {
return this.url;
}
@Override
public String getUsername() {
return this.username;
}
@Override
public String getPassword() {
return this.password;
}
@Override
public void setDriverClass(String driverClass) {
this.driverClass = driverClass;
}
@Override
public void setUrl(String url) {
this.url = url;
}
@Override
public void setUsername(String username) {
this.username = username;
}
@Override
public void setPassword(String password) {
this.password = password;
}
}
package io.xiaojl.jmx;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.rmi.registry.LocateRegistry;
import java.util.Iterator;
import java.util.Set;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
/**
* <p>Title: DBConfigAgent</p>
*
* <p>Description: 将MBean注册到MBeanServer</p>
*
* @author jilong.xiao
* @date 2018年9月11日
*/
public class DBConfigAgent {
public static void main(String[] args) throws MalformedObjectNameException,
InstanceAlreadyExistsException, MBeanRegistrationException,
NotCompliantMBeanException, IOException {
// 首先建立一个MBeanServer,MBeanServer用来管理我们的MBean,通常是通过MBeanServer来获取我们MBean的信息
MBeanServer mbServer = ManagementFactory.getPlatformMBeanServer();
String domainName = "OurMBean";
ObjectName on = new ObjectName(domainName+":name=DBConfigMBean");
//注册到MBeanServer
DBConfigMBean dbConfigMBean = new DBConfig();
mbServer.registerMBean(dbConfigMBean , on);
System.out.println("---DBConfigMBean注册完成----");
Set<ObjectInstance> beans = mbServer.queryMBeans(null, null);
Iterator<ObjectInstance> it = beans.iterator();
while(it.hasNext()){
ObjectInstance next = it.next();
ObjectName name = next.getObjectName();
System.out.println("\t已经注册的MBean有:"+name);
}
//注册一个端口,绑定url后,客户端就可以使用rmi通过url方式来连接JMXConnectorServer
LocateRegistry.createRegistry(9001);
String serviceURL = "service:jmx:rmi:///jndi/rmi://localhost:9001/jmxrmi";
JMXServiceURL url = new JMXServiceURL(serviceURL);
//创建JMXConnectorServer
JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbServer);
//启动
cs.start();
System.out.println("---JMXConnectorServer启动完成----");
}
}
---OurMBean注册完成---- 已经注册的MBean有:java.lang:type=OperatingSystem 已经注册的MBean有:java.lang:type=Compilation 已经注册的MBean有:java.lang:type=MemoryPool,name=PS Old Gen 已经注册的MBean有:JMImplementation:type=MBeanServerDelegate 已经注册的MBean有:java.lang:type=Memory 已经注册的MBean有:java.lang:type=MemoryPool,name=PS Perm Gen 已经注册的MBean有:java.lang:type=Runtime 已经注册的MBean有:java.nio:type=BufferPool,name=direct 已经注册的MBean有:java.lang:type=GarbageCollector,name=PS MarkSweep 已经注册的MBean有:java.nio:type=BufferPool,name=mapped 已经注册的MBean有:java.lang:type=Threading 已经注册的MBean有:java.lang:type=GarbageCollector,name=PS Scavenge 已经注册的MBean有:com.sun.management:type=HotSpotDiagnostic 已经注册的MBean有:java.lang:type=ClassLoading 已经注册的MBean有:java.lang:type=MemoryPool,name=PS Survivor Space 已经注册的MBean有:java.lang:type=MemoryManager,name=CodeCacheManager 已经注册的MBean有:java.lang:type=MemoryPool,name=Code Cache 已经注册的MBean有:java.lang:type=MemoryPool,name=PS Eden Space 已经注册的MBean有:java.util.logging:type=Logging 已经注册的MBean有:OurMBean:name=DBConfigMBean ---JMXConnectorServer启动完成----
package io.xiaojl.jmx;
import java.io.IOException;
import java.util.List;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
/**
* <p>Title: JMXClient</p>
*
* <p>Description: 客户端:可以获取jmx connector,并展示HelloMBean的一些信息,属性,及调用其方法</p>
*
* @author jilong.xiao
* @date 2018年9月11日
*/
public class JMXClient {
static final String serviceURL = "service:jmx:rmi:///jndi/rmi://localhost:9001/jmxrmi";
public static void main(String[] args) throws IOException, MalformedObjectNameException,
AttributeNotFoundException, InstanceNotFoundException,
MBeanException, ReflectionException {
JMXServiceURL url = new JMXServiceURL(serviceURL);
JMXConnector connect = JMXConnectorFactory.connect(url);
MBeanServerConnection connection = connect.getMBeanServerConnection();
System.out.println("获取MBeanServer中的所有Domain:");
String[] domains = connection.getDomains();
for(String domain:domains){
System.out.println("\tdomain:"+domain);
}
String domainName = "OurMBean";
ObjectName on = new ObjectName(domainName+":name=DBConfigMBean");
System.out.println("设置"+on+"的相关资源:注意属性名称首字母大写");
AttributeList attributes = new AttributeList();
attributes.add(new Attribute("DriverClass", "com.mysql.jdbc.Driver"));
attributes.add(new Attribute("Url", "jdbc:mysql://127.0.0.1:3306/xiaojldb"));
attributes.add(new Attribute("Username", "root"));
attributes.add(new Attribute("Password", "root"));
connection.setAttributes(on, attributes);
System.out.println("获取"+on+"的相关资源:");
//Object driverClass = connection.getAttribute(on, "DriverClass");
//System.out.println("\tdriverClass="+driverClass);
String[] attnames = {"DriverClass","Url","Username","Password"};
AttributeList attList = connection.getAttributes(on, attnames);
List<Attribute> list = attList.asList();
for(Attribute att: list){
System.out.println("\t"+att.getName()+"="+att.getValue());
}
}
}
获取MBeanServer中的所有Domain: domain:OurMBean domain:java.nio domain:JMImplementation domain:com.sun.management domain:java.lang domain:java.util.logging 设置OurMBean:name=DBConfigMBean的相关资源:注意属性名称首字母大写 获取OurMBean:name=DBConfigMBean的相关资源: DriverClass=com.mysql.jdbc.Driver Url=jdbc:mysql://127.0.0.1:3306/xiaojldb Username=root Password=root
原文作者:爱折腾的稻草
原文出处:GitShare
商业用途请与作者联系!
今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
上一篇
已是最后文章
下一篇
已是最新文章