java-jmx使用
先粘一段内容
1、程序初哥一般是写死在程序中,到要改变的时候就去修改代码,然后重新编译发布。 2、程序熟手则配置在文件中(JAVA一般都是properties文件),到要改变的时候只要修改配置文件,但还是必须重启系统,以便读取配置文件里最新的值。 3、程序好手则会写一段代码,把配置值缓存起来,系统在获取的时候,先看看配置文件有没有改动,如有改动则重新从配置里读取,否则从缓存里读取。 4、程序高手则懂得物为我所用,用JMX把需要配置的属性集中在一个类中,然后写一个MBean,再进行相关配置。另外JMX还提供了一个工具页,以方便我们对参数值进行修改。
JMX的全称为Java Management Extensions. 顾名思义,是管理Java的一种扩展。这种机制可以方便的管理正在运行中的Java程序。常用于管理线程,内存,日志Level,服务重启,系统环境等。
jmx整体架构:
1, Mbean准备
1, 先建立需要连接的接口
package com.wenbronk.le.iris.jmx; /** * 实现接口, 可在jconsoler中调用属性 */ public interface HelloMBean { public String getName(); public void setName(String name); public String getAge(); public void setAge(String age); public void helloWorld(); public void helloWorld(String str); public void getTelephone(); }
2, 实体类继承
package com.wenbronk.le.iris.jmx; import ch.qos.logback.core.joran.spi.NoAutoStart; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; /** * 必须实现 Mbean, 才可以进行注册 */ @NoArgsConstructor @AllArgsConstructor public class Hello implements HelloMBean { private String name; private String age; @Override public String getName() { System.out.println("get name::" + name); return name; } @Override public void setName(String name) { this.name = name; System.out.println("set name " + name); } @Override public String getAge() { System.out.println("get age::" + age); return age; } @Override public void setAge(String age) { this.age = age; System.out.println("set age " + age); } @Override public void helloWorld() { System.out.println("hello world"); } @Override public void helloWorld(String str) { System.out.println("hello world " + str); } @Override public void getTelephone() { System.out.println("get telephone"); } }
2, 使用java命令行指定
3,
package com.wenbronk.le.iris.jmx.local; import com.wenbronk.le.iris.jmx.Hello; import org.junit.Test; import javax.management.*; import java.lang.management.ManagementFactory; public class HelloAgent { public static void main(String[] args) throws MalformedObjectNameException, NotCompliantMBeanException, InstanceAlreadyExistsException, MBeanRegistrationException, InterruptedException { MBeanServer server = ManagementFactory.getPlatformMBeanServer(); Hello hello = new Hello(); // com.le.iris:type=ZhixinSource/QPS 域名:name=MBean名称 ObjectName helloName = new ObjectName("com.wenbronk.le.jmxBean:name=" + hello.getClass().getName()); ObjectInstance objectInstance = server.registerMBean(hello, helloName); Thread.sleep(60*1000*1000); } }
需要添加password等, 并指定权限
jmx.access
monitor readonly admin readwrite
jmx.password
monitor com.le.big
admin com.le.big
启动参数指定:
JMX_PORT=12345 JAVA_OPTS="-server \ -Dcom.sun.management.jmxremote\ -Dcom.sun.management.jmxremote.authenticate=true\ -Dcom.sun.management.jmxremote.password.file=jmx.password\ -Dcom.sun.management.jmxremote.access.file=jmx.access\ -Dcom.sun.management.jmxremote.ssl=false\ -Dcom.sun.management.jmxremote.port=${JMX_PORT}\ -Dcom.sun.management.jmxremote.local.only=false\ -Djava.rmi.server.hostname=${IP}\ -Diris.hostname=${IP}\ -Xmx${MEM}m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=4\ " nohup java ${JAVA_OPTS} -jar ${APP_JAR_NAME} ${params} 1>>${APP_HOME}/nohup.log 2>&1 &
2, 使用java指定远程连接方式:
3, agentserver的编写
package com.wenbronk.le.iris.jmx.remote; import com.wenbronk.le.iris.jmx.Hello; import com.wenbronk.le.iris.jmx.Testtt; import javax.management.MBeanServer; import javax.management.ObjectInstance; import javax.management.ObjectName; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; import java.io.IOException; import java.lang.management.ManagementFactory; import java.net.MalformedURLException; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; /** * 开启后, 可通过jconsoler进行连接 */ public class HelloAgentRemote { public static void main(String[] args) throws Exception { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); Hello hello = new Hello("vini", "23");
// 试了下, name 和 type没啥区别 ObjectName helloName = new ObjectName("com.wenbronk.le.jmxBean:name=" + hello.getClass().getSimpleName()); //ObjectName helloName1 = new ObjectName("com.wenbronk.le.jmxBean:type=" + hello.getClass().getSimpleName()); Testtt testtt = new Testtt(); ObjectName testtName = new ObjectName("com.wenbronk.le.jmxBean:type=" + testtt.getClass().getSimpleName()); //ObjectName testtName1 = new ObjectName("com.wenbronk.le.jmxBean:name=" + testtt.getClass().getSimpleName()); System.out.println(hello.getClass().getSimpleName()); ObjectInstance instance = mbs.registerMBean(hello, helloName); //ObjectInstance instance3 = mbs.registerMBean(hello, helloName1); ObjectInstance instance2 = mbs.registerMBean(testtt, testtName); //ObjectInstance instance4 = mbs.registerMBean(testtt, testtName1); try { // 注册一个端口并绑定 Registry registry = LocateRegistry.createRegistry(9999); JMXServiceURL jmxServiceURL = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi"); //service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi JMXConnectorServer jmxConnectorServer = JMXConnectorServerFactory.newJMXConnectorServer(jmxServiceURL, null, mbs); jmxConnectorServer.start(); }catch (Exception e) { e.printStackTrace(); } } }
此时可以通过jconsoler工具进行连接了,
4, 或者自己实现客户端进行连接
package com.wenbronk.le.iris.jmx.remote; import com.wenbronk.le.iris.jmx.HelloMBean; import javax.management.*; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; import java.io.IOException; import java.net.MalformedURLException; /** * 远程连接jmx */ public class Client { public static void main(String[] args) throws Exception { JMXServiceURL jmxServiceURL = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi"); JMXConnector connect = JMXConnectorFactory.connect(jmxServiceURL, null); MBeanServerConnection mBeanServerConnection = connect.getMBeanServerConnection(); String[] domains = mBeanServerConnection.getDomains(); for (int i = 0; i < domains.length; i++) { String obj = domains[i]; System.out.printf("domian[%d] = %s", i, domains[i].toString()); System.out.println(); } // 注册名和之前server的一致 ObjectName objectName = new ObjectName("com.wenbronk.le.jmxBean:name=Hello"); // 获取参数 getParam(mBeanServerConnection, objectName); System.out.println("get params======================"); // 更改参数 changeParams(mBeanServerConnection, objectName); getParam(mBeanServerConnection, objectName); System.out.println("set params======================"); useMethod(mBeanServerConnection, objectName); getParam(mBeanServerConnection, objectName); System.out.println("useMethod.========================"); } /** * 对method的调用, 采用反射的方式进行 */ public static void useMethod(MBeanServerConnection connection, ObjectName objectName) { HelloMBean helloMBean = MBeanServerInvocationHandler.newProxyInstance(connection, objectName, HelloMBean.class, true); String age = helloMBean.getAge(); String name = helloMBean.getName(); helloMBean.setAge("2323223"); helloMBean.helloWorld("nchar"); } /** * 可进行相关参数修改 * 通过setAttribute、getAttrubute方法来进行操作,则属性的首字母要大写 */ public static void changeParams(MBeanServerConnection mBeanServerConnection, ObjectName objectName) throws AttributeNotFoundException, InvalidAttributeValueException, ReflectionException, IOException, InstanceNotFoundException, MBeanException { mBeanServerConnection.setAttribute(objectName, new Attribute("Name", "hangzhou")); mBeanServerConnection.setAttribute(objectName, new Attribute("Age", "1990")); } /** * 获取参数 */ public static void getParam(MBeanServerConnection connection, ObjectName objectName) throws AttributeNotFoundException, MBeanException, ReflectionException, InstanceNotFoundException, IOException { String age = (String) connection.getAttribute(objectName, "Age"); String name = (String) connection.getAttribute(objectName, "Name"); System.out.println("name " + name + " age: " + age); } }
https://www.cnblogs.com/dongguacai/p/5900507.html