JMX自動監控Java應用 解決well-known file is not secure
前言
最近在做一個監控的Agent組件開發工作,主要就是收集各種系統Metrics資訊,然後上報給監控系統,以便進行監控和警示。目標就是要做到自動化:自動探索服務,動態探測服務,監控自動營運化,外掛程式化等等。
在Java應用監控這一塊,主要就是監控Java應用的JMX資訊。為了能夠自動探索Java應用,自動連接JMX,做了不少嘗試。本文就是分享,其中的一個問題的解決,把問題的解決思想記錄下來。 什麼是well-known file is not secure
當我們要串連VM的時候,如JMX,jmap,jstack時,VM會檢查/tmp/hsperfdata_$USER/$PID這樣的一個檔案,它會檢查執行該命令的使用者,是否和hsperfdata_$USER這個檔案所屬的使用者一致,如果不一致,就會出現well-known file is not secure這個異常,並拒絕串連 怎樣通過JMX串連Java應用並監控
JMX串連都是通過一個連接字串,調用JMXConnectorFactory.connect()方法建立串連。一般而言,JMX的連接字串有兩種擷取方法: 第一種是手動指定形如service:jmx:rmi:///jndi/rmi://host:ip/jmxrmi的JMX Remote URL。 第二種則是先使用VirtualMachine.list()方法得到本地的所有JMX資訊,然後通過Attach得到相關Pid的com.sun.management.jmxremote.localConnectorAddress進行串連。
第一種方法,需要在java應用啟動時,指定開啟JMX Remote,如可添加如下參數
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=${JMXport} -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
這種方法的好處就是沒有well-known file is not secure這種問題,但是這樣就需要手動設定串連資訊,也就失去了標題所述的自動連接,自動監控。
第二種方法,能夠實現自動探測本地的應用,無論應用是否有開啟JMX Remote的功能,都是可以串連。但是缺點就是會存在well-known file is not secure異常,就是當目標Java應用和本程式啟動的使用者不一樣時,就會出現這個異常。所以就需要結合兩個方法一起使用。 怎樣結合兩者。
話不多說,開門見山。
兩者結合的方案就是,先使用第二種方法進行本地的Java應用掃描,無論目標應用是不是同一個使用者啟動,都是可以擷取得到,並且也能夠擷取到它的Pid。然後針對每個應用,先進行第二中方法的串連,如果串連失敗,則代表該應用存在well-known file is not secure異常。然後,就可以根據該應用的Pid,使用 ps -aux | grep Pid的方式,擷取到應用的啟動命令,然後解析啟動命令,擷取啟動命令中的com.sun.management.jmxremote.port參數值port,然後根據該port,使用本地的IP地址127.0.0.1自動構建JMX Remote URL串連。
當然,這其中如果應用啟動時,設定了參數-Dcom.sun.management.jmxremote.authenticate=true,則代表該JMX有授權認證,需要登入名稱和密碼才能串連。我的解決方案是解析/etc/profile檔案,擷取JAVA_HOME地址,然後解析JAVA_HOME/jre/lib/management/jmxremote.access和JAVA_HOME/jre/lib/management/jmxremote.password檔案的內容擷取使用者名稱和密碼。
但是,由於java對這兩個檔案有嚴格的使用者權限控制:必須是運行該程式的使用者才能進行讀寫,不然java應用會拒絕啟動。所以即使是root使用者啟動,只要不是相同的使用者,也無法訪問這兩個檔案。
凡事總會有解決辦法,我的方案就是對對應的設定檔進行拷貝到一個臨時檔案,並授權777(因為是監控,所以本程式基本上都是root身份運行),然後擷取臨時檔案內容,解析擷取使用者名稱和密碼,解析完了再刪除臨時檔案。這樣就可以擷取到JMX Remote串連的授權使用者和密碼。
最後補充一下,如果目標應用沒有開啟JMX Remote Connect的功能而且啟動的使用者也不同,那麼應該是無法使用JMX串連了,除非使用相同的使用者,再啟動一個進程進行串連。不過,正常而言,公司應該都會開啟Java應用的JMX Remote功能。
不過,又有一個問題來了
如果Java是跑在Docker container上怎麼辦。怎樣同時監控Docker容器和容器內的應用呢。有時間再分享這個的解決方案。