Java Agent & JMX Exporter

Mozart
5 min readDec 24, 2020

--

最近因為工作上的需要,需要使用jmx_exporter 並用 java agent的方式收集程式在Kubernetes 執行時的metrics。但對於 java agent 和 jmx_exporter 不太了解。所以就整理一下工作上用到的相關知識。

1. 什麼是JMX: JMX 是Java Management Extensions, 它是一個Java 平台的管理和監控接口。不管任何系統,對於 運作中的程式進行監控非常重要,Java 程式也是。我們一定會想知道Java 應用程式目前的情況。例如,分配了多少Memory, 用了多少Memory,目前有多少Thread,有多少 Thread 目前在Sleep。我們可以透過 JMX的提供的介面來知道這些資訊。

2.什麼是 JMX Exporter: 比較完整的名稱應該是 JMX to Prometheus exporter。JMX Exporter 透過JMX 介面收集 JVM 相關的metrics。並會起一個 HTTP server ,把收集到的metrics 以 HTTP 的方式expose 出來,所以 Prometheus 就可以透過 HTTP 的方式收集到相關的資訊。簡單來說,JMX Exporter 利用Java的JMX 機制來讀取JVM 執行時的監控數據,然後將其轉換為Promtheus 可以接受的格式,以便讓Prometheus 收集這些結果。而 JMX Exporter 建議啟動的方式就是透過 Java agent.

3.什麼是 Java Agent:

  • javaagent 是可以指定在 java command line的一個參數。他可以指定一個jar file.
  • 在這個 jar包裡的,必須要有一個對應的類別,該類別要實作premain() 方法
  • jar file 裡的 MANIFEST.MF 裡必須要指定premain-class 是哪一個

所以在程式啟動時,一般的java 程式會執行main function,若有指定java agent,會在執行main方法前先執行premain funciton。他可以在Java runtime 即時更改byte(有點像是AOP的效果)。所以你就可以攔截類別的byte clode,作一些其他的應用,比如說在每個method的前後記錄時間,就可以計算執行時間。

所以如果把你的程式運作在K8S,就可以利用Java agnet的方式收集JVM的資料,並讓Prometheus收集,其方式如下

  1. 先下載對應的Prometheus java agent library,我這邊下載的是jmx_prometheus_javaagent-0.12.0.jar
  2. 記得要把下列參數在啟動你的程式時傳給 JVM
java XXX -javaagent:/root/jmx_exporter/jmx_prometheus_javaagent-0.12.0.jar=3010:/root/jmx_exporter/config.yaml -jar XXX.jar

3010 表示 Prometheus 要從哪個 port抓資料。而 config.yaml是定義如何把從JMX 收集到的資訊轉成Prometheus 可以接收的格式。這個我的範例如下:

startDelaySeconds: 0hostPort: 127.0.0.1:11001 # 這表示JMX 對外expose的port是11001。所以 JMX Exporter會從這個port拉資料,並轉換成Prometheus 可以接收的格式,再用http 的方式(以上述例子是3010 port),讓Prometheus可以抓到資料ssl: falselowercaseOutputName: falselowercaseOutputLabelNames: falsewhitelistObjectNames: [“kafka.*:*”]rules:- pattern : kafka.(.+)<type=(.+), client-id=(.+), topic=(.+)><>(.+rate|.+total|.+avg|.+max|.+count)name: kafka_$1_$2_$3_$5labels:topic: “$4”- pattern : kafka.(.+)<type=(.+), client-id=(.+)><>(.+rate|.+total|.+avg|.+max|.+count)name: kafka_$1_$2_$3_$4- pattern : kafka.tools<type=(.+), name=(.+)><>Valuename: kafka_tools_$1_$2

--

--