JMX最常見(jiàn)的場(chǎng)景是監(jiān)控Java程序的基本信息和運(yùn)行情況发钝,任何Java程序都可以開(kāi)啟JMX,然后使用JConsole或Visual VM進(jìn)行預(yù)覽漩符。下圖是使用Jconsle通過(guò)JMX查看Java程序的運(yùn)行信息
為Java程序開(kāi)啟JMX很簡(jiǎn)單一喘,只要在運(yùn)行Java程序的命令后面指定如下命令即可
-Djava.rmi.server.hostname=127.0.0.1
-Dcom.sun.management.jmxremote.port=1000
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
我們從Jconsole的視圖標(biāo)簽中見(jiàn)到,JConsole通過(guò)JMX展示的信息都是Java程序的通用信息嗜暴,如內(nèi)存情況凸克、線程情況、類加載情況等闷沥,換言之萎战,只要是Java程序就都具備這些信息。這些信息為我們優(yōu)化程序性能狐赡、排查BUG非常有用撞鹉,而JMX就是獲取這些信息的基礎(chǔ),因此它是一種非常有用的技術(shù)颖侄。
然而JMX的強(qiáng)大遠(yuǎn)不止此鸟雏,它出了能提供一些通用的信息以外,還能通過(guò)特定的編程接口提供一些針對(duì)具體程序的專有信息并在JConsole等JMX客戶端工具中展示览祖,具體點(diǎn)說(shuō)就是程序員可以把需要展示的信息放在一種叫做MBean的Java對(duì)象內(nèi)孝鹊,然后JConsole之類的客戶端工具可以連接到JMX服務(wù),識(shí)別MBean并在圖形界面中顯示展蒂。從純抽象的角度觸發(fā)又活,這其實(shí)有點(diǎn)像瀏覽器發(fā)送一個(gè)請(qǐng)求給http服務(wù)器,然后http服務(wù)器執(zhí)行瀏覽器的請(qǐng)求并返回相應(yīng)的數(shù)據(jù)锰悼,從某種角度來(lái)說(shuō)JConsole和JMX也是以這種方式工作的柳骄,只是它們使用的協(xié)議不是http,交換數(shù)據(jù)協(xié)議格式不是http數(shù)據(jù)包箕般,但是他們的確是以客戶端/服務(wù)器這種模式工作的耐薯,而且完成的事情也差不多。
那么既然有了http丝里,JMX又有何存在意義呢曲初。 事實(shí)上,JMX能完成的任務(wù)通過(guò)http的確都能完成杯聚,只不過(guò)某些情況下用JMX來(lái)做會(huì)更加方便臼婆。
比如說(shuō)你需要知道服務(wù)器上個(gè)運(yùn)行中程序的相關(guān)信息, 如執(zhí)行了多少次數(shù)據(jù)庫(kù)操作幌绍、任務(wù)隊(duì)列中有多少個(gè)任務(wù)在等待處理
最常用的解決方案颁褂,我們會(huì)在程序中啟動(dòng)一個(gè)http服務(wù),當(dāng)接收到來(lái)自客戶端的請(qǐng)求這些信息的請(qǐng)求時(shí)傀广,我們的http處理程序會(huì)獲得這些信息痢虹,并轉(zhuǎn)換成特定格式的數(shù)據(jù)如JSON返回給客戶端,客戶端會(huì)以某種方式展現(xiàn)這些信息主儡。
如以JMX作為解決方案奖唯,核心流程也是如此,但在數(shù)據(jù)的交換方式上會(huì)略有不同糜值。
下面我們展示JMX是如何完成此任務(wù)的丰捷。
一、定義一個(gè)展示所需信息的MBean接口
public interface ServerInfoMBean {
int getExecutedSqlCmdCount();
}
在使用 Standard Mbean 作為數(shù)據(jù)傳輸對(duì)象的情況下這個(gè)接口的定義是必須的寂汇, 并且接口名稱必須以“MBean”這個(gè)單詞結(jié)尾病往。
二、實(shí)現(xiàn)具體的MBean
public class ServerInfo implements ServerInfoMBean {
public int getExecutedSqlCmdCount() {
return Dbutil.getExecutedSqlCmdCount();
}
}
三骄瓣、在程序的某個(gè)地方啟動(dòng)JMX服務(wù)并注冊(cè)ServerInfoMBean
public static void main(String[] args) throws JMException, Exception{
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("serverInfoMBean:name=serverInfo");
server.registerMBean(new ServerInfo(), name);
}
四停巷、運(yùn)行程序,并通過(guò)JConsole查看
如果程序運(yùn)行在本地,Jconsole會(huì)自動(dòng)檢測(cè)到程序的進(jìn)程畔勤,鼠標(biāo)雙擊進(jìn)入即可
在JConsole下面即會(huì)展示我們定義的MBean中的內(nèi)容
那么假如Java程序并非運(yùn)行在本地而是運(yùn)行在遠(yuǎn)端服務(wù)器上我們應(yīng)該如何通過(guò)客戶端去連接呢蕾各, 很簡(jiǎn)單,只要使用JDK提供的JMX類庫(kù)監(jiān)聽(tīng)端口提供服務(wù)即可
public class Main {
public static void main(String[] args) throws JMException, Exception{
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("serverInfoMBean:name=serverInfo");
server.registerMBean(new ServerInfo(), name);
LocateRegistry.createRegistry(8081);
JMXServiceURL url = new JMXServiceURL
("service:jmx:rmi:///jndi/rmi://localhost:8081/jmxrmi");
JMXConnectorServer jcs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);
jcs.start();
}
}
或者在啟動(dòng)Java程序指定命令行參數(shù)也
-Djava.rmi.server.hostname=127.0.0.1
-Dcom.sun.management.jmxremote.port=10086
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
<br />然后使用JConsole的連接遠(yuǎn)端進(jìn)程功能即可
其余的操作和本地?zé)o差庆揪。
這相對(duì)于提供一個(gè)http服務(wù)來(lái)完成任務(wù)是不是要簡(jiǎn)單了不少式曲,http是一個(gè)更加抽象、應(yīng)用面更廣泛缸榛、功能更強(qiáng)大的服務(wù)吝羞,因此所作的工作也要更多一些。JMX則是一個(gè)更加具體内颗、應(yīng)用面不那么廣钧排、功能也沒(méi)有http強(qiáng)大的服務(wù),不過(guò)呢它勝在解決特定問(wèn)題更加輕松方便均澳,上面的示例已經(jīng)很好的說(shuō)明了卖氨。
此外,JMX和Jconsole并不僅僅只能展示數(shù)據(jù)负懦,它還能執(zhí)行Java方法筒捺。以上面的示例為基礎(chǔ)我們?cè)龠M(jìn)行一系列改進(jìn)。
一纸厉、擴(kuò)展ServerInfoMBean接口和實(shí)現(xiàn)的類
public interface ServerInfoMBean {
int getExecutedSqlCmdCount();
void printString(String fromJConsole);
}
public class ServerInfo implements ServerInfoMBean {
public int getExecutedSqlCmdCount() {
return 100;
}
public void printString(String fromJConsole) {
System.out.println(fromJConsole);
}
}
二系吭、運(yùn)行程序并使用JConsole連接
mbean頁(yè)簽中出現(xiàn)了我們新添加的方法
三、點(diǎn)擊printString按鈕調(diào)用方法
方法被調(diào)用颗品,同時(shí)控制臺(tái)也打印了通過(guò)Jconsole傳遞的參數(shù)
這里只是講解了JMX的用處和最基礎(chǔ)的使用方法肯尺,顯然JMX真正提供的功能遠(yuǎn)不及此,比如它可以不用JConsole而是客戶端編程的方式訪問(wèn)等等躯枢, 有興趣的同學(xué)可以深入研究则吟。
總而言之, 我覺(jué)得JMX是一種小巧精悍的工具锄蹂,在不需要大張旗鼓的通過(guò)http或者其他server\client方式提供服務(wù)時(shí)氓仲,就是他發(fā)揮用處的時(shí)機(jī)了。