Java中JMX管理器的作用,项目中有什么具体使用?
作者:wuxinliulei
鏈接:https://www.zhihu.com/question/36688387/answer/68667704
來(lái)源:知乎
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
?
JMX是一種JAVA的正式規(guī)范,它主要目的是讓程序有被管理的功能。
那么怎么理解所謂的“被管理”呢?試想你開(kāi)發(fā)了一個(gè)軟件(如WEB網(wǎng)站),它是在24小時(shí)不簡(jiǎn)斷運(yùn)行的,那么你可能會(huì)想要“監(jiān)控”這個(gè)軟件的運(yùn)行情況,比如收到了多少數(shù)據(jù),有多少人登錄等等。或者你又想“配置”這個(gè)軟件,比如現(xiàn)在訪問(wèn)人數(shù)比較多,你想把數(shù)據(jù)連接池設(shè)置得大一些;每天的UV、PV是多少;又或者在業(yè)務(wù)高峰的期間,你想對(duì)接口進(jìn)行限流,就必須去修改接口并發(fā)的配置值。
應(yīng)用場(chǎng)景:中間件軟件WebLogic的管理頁(yè)面就是基于JMX開(kāi)發(fā)的,而JBoss則整個(gè)系統(tǒng)都基于JMX構(gòu)架。
對(duì)于一些參數(shù)的修改,網(wǎng)上有一段描述還是比較形象的:
1、程序初哥一般是寫(xiě)死在程序中,到要改變的時(shí)候就去修改代碼,然后重新編譯發(fā)布。
2、程序熟手則配置在文件中(JAVA一般都是properties文件),到要改變的時(shí)候只要修改配置文件,但還是必須重啟系統(tǒng),以便讀取配置文件里最新的值。
3、程序好手則會(huì)寫(xiě)一段代碼,把配置值緩存起來(lái),系統(tǒng)在獲取的時(shí)候,先看看配置文件有沒(méi)有改動(dòng),如有改動(dòng)則重新從配置里讀取,否則從緩存里讀取。
4、程序高手則懂得物為我所用,用JMX把需要配置的屬性集中在一個(gè)類(lèi)中,然后寫(xiě)一個(gè)MBean,再進(jìn)行相關(guān)配置。另外JMX還提供了一個(gè)工具頁(yè),以方便我們對(duì)參數(shù)值進(jìn)行修改。
?
讓開(kāi)發(fā)者和管理者可以獲取程序運(yùn)行的狀態(tài)以及動(dòng)態(tài)的修改程序的相關(guān)配置。
SUN依據(jù)這個(gè)規(guī)范在JDK提供了JMX接口,而根據(jù)這個(gè)接口的實(shí)現(xiàn)則有很多種,比如Weblogic的JMX實(shí)現(xiàn)、MX4J、JBoss的JMX實(shí)現(xiàn)。
我們經(jīng)常使用的JDK中SUN公司的實(shí)現(xiàn)在java.lang.management包下。
JMX架構(gòu)圖:
MBean 即 managed beans 被管理的Beans
?
從圖中我們可以看到,JMX的結(jié)構(gòu)一共分為三層:
1、基礎(chǔ)層:主要是MBean,被管理的資源。
MBean分為如下四種,我接下來(lái)主要介紹standard MBean
類(lèi)型描述standard MBean這種類(lèi)型的MBean最簡(jiǎn)單,它能管理的資源(包括屬性,方法,時(shí)間)必須定義在接口中,然后MBean必須實(shí)現(xiàn)這個(gè)接口。它的命名也必須遵循一定的規(guī)范,例如我們的MBean為Hello,則接口必須為HelloMBean。dynamic MBean必須實(shí)現(xiàn)javax.management.DynamicMBean接口,所有的屬性,方法都在運(yùn)行時(shí)定義open MBean此MBean的規(guī)范還不完善,正在改進(jìn)中model MBean與標(biāo)準(zhǔn)和動(dòng)態(tài)MBean相比,你可以不用寫(xiě)MBean類(lèi),只需使用javax.management.modelmbean.RequiredModelMBean即可。RequiredModelMBean實(shí)現(xiàn)了ModelMBean接口,而ModelMBean擴(kuò)展了DynamicMBean接口,因此與DynamicMBean相似,Model MBean的管理資源也是在運(yùn)行時(shí)定義的。與DynamicMBean不同的是,DynamicMBean管理的資源一般定義在DynamicMBean中(運(yùn)行時(shí)才決定管理那些資源),而model MBean管理的資源并不在MBean中,而是在外部(通常是一個(gè)類(lèi)),只有在運(yùn)行時(shí),才通過(guò)set方法將其加入到model MBean中。后面的例子會(huì)有詳細(xì)介紹
2、適配層:MBeanServer,主要是提供對(duì)資源的注冊(cè)和管理。
3、接入層:提供遠(yuǎn)程訪問(wèn)的入口。
JMX超詳細(xì)解讀 - 冬瓜蔡 - 博客園 這篇博客詳細(xì)介紹了三種使用JMX的方式,下面我提供一下自己實(shí)現(xiàn)的例程
?
import java.io.IOException; import java.lang.management.ManagementFactory; import java.rmi.registry.LocateRegistry; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.ObjectName; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL;import org.apache.log4j.Logger; import org.apache.log4j.xml.DOMConfigurator;import com.sun.jdmk.comm.HtmlAdaptorServer;public class ApplicationServer {private static HtmlAdaptorServer adaptorServer = null;private static javax.management.remote.JMXConnectorServer cs = null;private static Logger logger = null;private static ExecutorService cachedExecutors = null;private static void initExecutor(){cachedExecutors = Executors.newFixedThreadPool(2);}private static void exitExecutor(){cachedExecutors.shutdown();}public static void execute(final Runnable runnable){cachedExecutors.execute(runnable);}private static void initLogger(){System.out.println("configuring log4j with log4j.xml");DOMConfigurator.configure("log4j.xml");logger = Logger.getLogger("root");}private static void initHtmlJMX() throws Exception{MBeanServer server = MBeanServerFactory.createMBeanServer();ObjectName helloName = new ObjectName("jmx:name=HelloWorld");server.registerMBean(new Hello(), helloName);ObjectName adapterName = new ObjectName("HelloAgent:name=htmladapter,port=8081");adaptorServer = new HtmlAdaptorServer();server.registerMBean(adaptorServer, adapterName);adaptorServer.start();logger.info("start jmx html server");}private static int initProtogenesisJMX() throws Exception{String port1Str = System.getProperty("com.jmxport1");String port2Str = System.getProperty("com.jmxport2");if (port1Str == null || port2Str == null){logger.error("jmx端口未通過(guò)系統(tǒng)屬性設(shè)置");return -1;}final int port1 = Integer.valueOf(port1Str);final int port2 = Integer.valueOf(port2Str);System.setProperty("java.rmi.server.randomIDs", "true");try{LocateRegistry.createRegistry(port2);}catch (java.rmi.server.ExportException ex){logger.error("err", ex);return -1;}MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();java.util.HashMap<String, Object> env = new java.util.HashMap<String, Object>();env.put("jmx.remote.x.password.file", "jmxremote.password");env.put("jmx.remote.x.access.file", "jmxremote.access");JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://127.0.0.1:" + port1 + "/jndi/rmi://127.0.0.1:" + port2+ "/jmxrmi");cs = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);try{cs.start();}catch (java.net.BindException ex){logger.error("端口已被占用", ex);return -2;}return 0;}public static void exitHtmlJMX(){adaptorServer.stop();}public static void exitProtogenesisJMX() throws IOException{cs.stop();}public static void init() throws Exception{initLogger();// initHtmlJMX();initProtogenesisJMX();initExecutor();}public static void exit() throws IOException{//exitHtmlJMX();exitProtogenesisJMX();exitExecutor();}public static void main(String[] args) throws Exception{System.setProperty("com.jmxport1", String.valueOf(7000));System.setProperty("com.jmxport2", String.valueOf(7001));init();MBeanServer server = java.lang.management.ManagementFactory.getPlatformMBeanServer();ObjectName helloName = new ObjectName("jmxBean:name=stopper");server.registerMBean(new Stopper(), helloName);}public interface StopperMBean{void stop() throws IOException;}public static class Stopper implements StopperMBean{public void stop() throws IOException{ApplicationServer.exit();}}}?
import java.text.SimpleDateFormat; import java.util.HashMap;import javax.management.MBeanServerConnection; import javax.management.ObjectName; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL;public class JMXClient {/*** * @param args* host port username password bean name method ...params* @throws Exception*/public static void main(String[] args) throws Exception{if ((args.length < 6) || (args.length % 2 != 0)){logErr("params error");return;}final String host = args[0];final int rmiPort = Integer.valueOf(args[1]).intValue();final String username = args[2];final String password = args[3];final ObjectName objectName = new ObjectName(args[4]);final String methodName = args[5];final HashMap<String, String[]> jmxParamsHashMap = new HashMap<String, String[]>();final String[] usernameAndPassword ={ username, password };jmxParamsHashMap.put("jmx.remote.credentials", usernameAndPassword);final String serviceUrl = new StringBuilder().append("service:jmx:rmi:///jndi/rmi://").append(host).append(":").append(rmiPort).append("/jmxrmi").toString();final JMXServiceURL jmxServiceURL = new JMXServiceURL(serviceUrl);final JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxServiceURL, jmxParamsHashMap);if (jmxConnector == null){logErr(new StringBuilder().append("connect to jmx failed, url=").append(jmxServiceURL).toString());return;}log(new StringBuilder().append("JMXConnector=").append(jmxConnector.toString()).toString());Object[] paramsValue = null;String[] paramsClassName = null;final MBeanServerConnection mBeanServerConnection = jmxConnector.getMBeanServerConnection();final Object localObject = mBeanServerConnection.invoke(objectName, methodName, paramsValue, paramsClassName);log(new StringBuilder().append("invoke method success, name=").append(objectName).append(", operation=").append(methodName).append(", retvalue=").append(localObject == null ? "void" : localObject.toString()).toString());}static void log(String paramString){final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss : ");final StringBuilder sBuilder = new StringBuilder();sBuilder.append(simpleDateFormat.format(Long.valueOf(System.currentTimeMillis())));sBuilder.append(paramString);System.out.println(sBuilder.toString());}static void logErr(String paramString){final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss : ");final StringBuilder sBuilder = new StringBuilder();sBuilder.append(simpleDateFormat.format(Long.valueOf(System.currentTimeMillis())));sBuilder.append(paramString);System.err.println(sBuilder.toString());} }from:https://www.zhihu.com/question/36688387?
總結(jié)
以上是生活随笔為你收集整理的Java中JMX管理器的作用,项目中有什么具体使用?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 用 JMX 检测应用程序
- 下一篇: Git 分支 - rebase 变基