? ? ? 之前寫過一篇用容器技術(shù)快速構(gòu)建jvm監(jiān)控服務(wù)的文章,那篇側(cè)重講的是實(shí)現(xiàn),說的是“怎么做”的問題。這篇會(huì)去探討“為什么”,算是對(duì)前一篇的補(bǔ)充。
? ? ?什么是監(jiān)控
? ? ? 軟件技術(shù)雖然層出不窮,但本質(zhì)上大同小異。
? ? ? 在講JVM監(jiān)控之前,我們可以先類比一下現(xiàn)實(shí)生活經(jīng)常可以看到的視頻監(jiān)控。視頻監(jiān)控一般由攝像頭,網(wǎng)絡(luò)傳輸線,視頻服務(wù)器,監(jiān)控終端這幾個(gè)組件構(gòu)成。攝像頭用來采集視頻數(shù)據(jù)(有些攝像頭自帶轉(zhuǎn)碼,有些會(huì)有另外的轉(zhuǎn)碼器),網(wǎng)絡(luò)傳輸線用來傳輸數(shù)據(jù),視頻服務(wù)器用來處理和存儲(chǔ)數(shù)據(jù),監(jiān)控終端用來展示視頻圖像。在這里你可以看到,監(jiān)控的整個(gè)工作流,其實(shí)就是在跟數(shù)據(jù)打交道。只不過各個(gè)環(huán)節(jié)打交道的方式不同。JVM監(jiān)控也是如此,它的整個(gè)工作流也是圍繞數(shù)據(jù)進(jìn)行。
? ??JMX
? ? ? 監(jiān)控的第一步也是最重要的一步就是采集數(shù)據(jù)。假如現(xiàn)在讓你采集一個(gè)程序的運(yùn)行時(shí)信息,你會(huì)在程序里預(yù)先寫好數(shù)據(jù)采集的代碼,常見的場(chǎng)景如打日志。我們可以定義把日志打到文件里,標(biāo)準(zhǔn)輸出里,網(wǎng)絡(luò)協(xié)議里等等。jdk在的java.lang.management包中實(shí)現(xiàn)了采集JVM狀態(tài)數(shù)據(jù)的功能。java代碼很簡單,真正實(shí)現(xiàn)數(shù)據(jù)采集功能的是底層的native方法。這里不做過多討論。但是問題來了,并不是每個(gè)人在任何時(shí)候都需要監(jiān)控JVM的狀態(tài)。也并不是每個(gè)JVM都需要被監(jiān)控。所以我們需要一種動(dòng)態(tài)機(jī)制,能夠讓我們選擇用不用,在什么時(shí)候用,以何種頻率用。在我們自己寫程序的時(shí)候,通常使用配置文件或者環(huán)境變量等方式來達(dá)到這種目的。jdk則提供JMX來解決動(dòng)態(tài)管理的問題。
? ? ? ?JMX技術(shù)的實(shí)現(xiàn)分為三層架構(gòu)。第一層叫Instrumentation,用于管理使用JMX的資源。JMX定義:如果一個(gè)java類是使用JMX技術(shù)的,那么這個(gè)類的名字必須要以MBean或者M(jìn)XBean結(jié)尾。所以第一層的工作就是發(fā)現(xiàn)MBean,并把它們注冊(cè)到第二層,JMX Agent。JMX Agent可以控制注冊(cè)在其上的資源,也就是一些java類。并使得外部的管理程序可以使用這些資源。第三層叫Remote management,可以理解為用于幫助MBeanServer與外部管理程序連接的組件。如果要開啟JMX的功能,只需要在啟動(dòng)時(shí)設(shè)置com.sun.management.jmxremote.porty以及相關(guān)的參數(shù)即可。下面這段代碼簡單演示了如何獲取一個(gè)JVM的內(nèi)存使用態(tài):
? ? ? ?在上面的例子中,我們看到了某一時(shí)間點(diǎn)上的JVM內(nèi)存使用情況。這是一種監(jiān)控嗎?在特殊的情況下是的。有時(shí)候需要獲取某一時(shí)間點(diǎn)的JVM狀態(tài)。比如說在系統(tǒng)發(fā)生宕機(jī)前,hook在shutdown signal的JVM監(jiān)控,可以幫助分析系統(tǒng)為什么宕機(jī)。但在通常情況下,我們所說的監(jiān)控,是對(duì)事物狀態(tài)的連續(xù)觀測(cè)。我們可以把上面的代碼定義成一個(gè)job,用quartz這樣的框架去定時(shí)執(zhí)行。但這樣費(fèi)時(shí)費(fèi)力。更好的選擇是用那些已經(jīng)比較成熟的框架,谷歌的jmxTrans就是其中之一。有興趣的同學(xué)可以去了解一下。
? ? ?數(shù)據(jù)處理
? ? ? 實(shí)現(xiàn)了JVM狀態(tài)數(shù)據(jù)的持續(xù)采集之后該怎么做呢。一種選擇是我們可以把數(shù)據(jù)稍加處理,在前臺(tái)頁面展示成dashbord,就像jconsole那樣。但如果只是做到像jconsole那樣,是不能被稱為監(jiān)控服務(wù)的。一旦前端展示頁面的進(jìn)程退出,歷史的JVM狀態(tài)將無法追溯。而我們經(jīng)常需要追溯歷史數(shù)據(jù)。所以監(jiān)控?cái)?shù)據(jù)需要被存儲(chǔ),監(jiān)控服務(wù)才能更穩(wěn)定。我們依舊可以用自己的方法把數(shù)據(jù)直接存儲(chǔ),然后再抽取存儲(chǔ)的數(shù)據(jù),稍加處理傳給前臺(tái)的展示頁面。我們可以用es,mongoDB甚至是mysql等來完成這樣的工作。只要你不嫌麻煩,心中所念:所謂監(jiān)控?zé)o非就是處理數(shù)據(jù),你一定能成功。但市面上已經(jīng)有很多工具可以很好地完成這樣的工作,而且完成的還很好,很方便。你大可不必再費(fèi)心費(fèi)力自己實(shí)現(xiàn)一套。我們只需要稍加利用這些框架就好。在我搭建JVM監(jiān)控的時(shí)候,我用的是graphite。這是一款比較易用的工具,外部的易用一定意味著其內(nèi)部的精心設(shè)計(jì)與大量工作。有興趣的同學(xué)可以自行查閱。
? ? ? 數(shù)據(jù)展示
? ? ? ? 接下來就是數(shù)據(jù)展示的問題了,其實(shí)graphite本身是有數(shù)據(jù)展示的web服務(wù)的。它的優(yōu)點(diǎn)是,圖表都是自動(dòng)生成,無需配置。它的缺點(diǎn)是丑,不清晰,看著累。所以可以把graphite作為數(shù)據(jù)源,在grafana中展示。grafana可能大家都聽說過,但很多人對(duì)它有誤解。以為可以單獨(dú)用它來完成監(jiān)控,其實(shí)不是的。它主要還是被用作監(jiān)控報(bào)表,報(bào)表的原始數(shù)據(jù)來自配置的數(shù)據(jù)源。
? ? ? 總結(jié):
? ? ? ? 回過頭來看,要完成JVM監(jiān)控其實(shí)還是很容易的。如果不出什么幺蛾子,搭建的過程無非就是安裝和配置的過程。如果你用容器來完成,那簡直就跟搭積木一樣簡單了。但我要說的是,幺蛾子肯定是會(huì)出現(xiàn)的,只是時(shí)間的問題。要想搭出健壯的監(jiān)控系統(tǒng),一定需要勤學(xué)苦練。僅僅知道本文說的“為什么”問題也許還不夠。如果有機(jī)會(huì),下次再來深入探討下“是什么”的問題。