MXtrans + InfluxDB + Grafana實現Kafka性能指標監控
架構
一般系統監控通常分爲3部分:
-
數據採集
-
分析與轉換
-
展現(可視化)
數據採集
對於前端應用,一般需要埋點,對用戶的行爲進行記錄。 如果不埋點,則需要通過Pagespeed、PhantomJS這樣的工具去模擬用戶行爲進行測試。後端的系統通常有自己的性能指標。我們可以通過命令/腳本的方式進行採集。
JMX(Java Management Extensions,即Java管理擴展)是一個爲應用程序、設備、系統等管理功能的框架,通常可以用來監控和管理Java應用系統。
Kafka做爲一款Java應用,已經定義了豐富的性能指標,(可以參考 Kafka監控指標 ),通過JMX可以輕鬆對其進行監控。
測試
首先需要在Kafka上打開JMX
1.修改${kafka_home}/bin/kafka-server-start.sh , 增加一個JMX_PORT的配置,指定一個端口用於接受外部連接,注意如部署、運行在非root用戶下,必須指定1024以上端口
if [ "x$KAFKA_HEAP_OPTS" = "x" ]; then
export KAFKA_HEAP_OPTS="-Xmx1G -Xms1G"
export JMX_PORT="9999"
fi
2.重啓kafka
bin/kafka-server-stop.sh
bin/kafka-server-start.sh config/server.properties &
3.重啓後觀察可以發現JMX已經啓動了
$ps -ef | grep kafka
www 51065 1 0 Nov03 ? 00:08:20 /opt/vdian/java/bin/java -Xmx1G -Xms1G -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+DisableExplicitGC -Djava.awt.headless=true -Xloggc:/home/www/kafka_2.11-0.10.0.1/bin/../logs/kafkaServer-gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=9999 -Dkafka.logs.dir=/home/www/kafka_2.11-0.10.0.1/bin/../logs -Dlog4j.configuration=file:bin/../config/log4j.properties -cp :/home/www/kafka_2.11-0.10.0.1/bin/../libs/aopalliance-repackaged-2.4.0-b34.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/argparse4j-0.5.0.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/connect-api-0.10.0.1.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/connect-file-0.10.0.1.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/connect-json-0.10.0.1.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/connect-runtime-0.10.0.1.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/guava-18.0.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/hk2-api-2.4.0-b34.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/hk2-locator-2.4.0-b34.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/hk2-utils-2.4.0-b34.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jackson-annotations-2.6.0.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jackson-core-2.6.3.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jackson-databind-2.6.3.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jackson-jaxrs-base-2.6.3.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jackson-jaxrs-json-provider-2.6.3.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jackson-module-jaxb-annotations-2.6.3.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/javassist-3.18.2-GA.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/javax.annotation-api-1.2.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/javax.inject-1.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/javax.inject-2.4.0-b34.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/javax.servlet-api-3.1.0.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/javax.ws.rs-api-2.0.1.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jersey-client-2.22.2.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jersey-common-2.22.2.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jersey-container-servlet-2.22.2.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jersey-container-servlet-core-2.22.2.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jersey-guava-2.22.2.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jersey-media-jaxb-2.22.2.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jersey-server-2.22.2.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jetty-continuation-9.2.15.v20160210.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jetty-http-9.2.15.v20160210.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jetty-io-9.2.15.v20160210.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jetty-security-9.2.15.v20160210.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jetty-server-9.2.15.v20160210.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jetty-servlet-9.2.15.v20160210.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jetty-servlets-9.2.15.v20160210.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jetty-util-9.2.15.v20160210.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/jopt-simple-4.9.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/kafka-clients-0.10.0.1.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/kafka-log4j-appender-0.10.0.1.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/kafka-streams-0.10.0.1.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/kafka-streams-examples-0.10.0.1.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/kafka-tools-0.10.0.1.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/kafka_2.11-0.10.0.1-sources.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/kafka_2.11-0.10.0.1-test-sources.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/kafka_2.11-0.10.0.1.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/log4j-1.2.17.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/lz4-1.3.0.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/metrics-core-2.2.0.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/osgi-resource-locator-1.0.1.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/reflections-0.9.10.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/rocksdbjni-4.8.0.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/scala-library-2.11.8.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/scala-parser-combinators_2.11-1.0.4.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/slf4j-api-1.7.21.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/slf4j-log4j12-1.7.21.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/snappy-java-1.1.2.6.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/validation-api-1.1.0.Final.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/zkclient-0.8.jar:/home/www/kafka_2.11-0.10.0.1/bin/../libs/zookeeper-3.4.6.jar kafka.Kafka config/server.properties
$ netstat -an | grep 9999
tcp 0 0 :::9999 :::* LISTEN
4.在安裝了java的主機上運行jconsole,就會彈出一個控制檯,在可以看到MBean中的性能指標
指標採集
傳統的數據採集方案,一般是先開發數據採集的腳本,然後藉助nagios、zabbix這樣的監控軟件來調度執行,並將採集到的數據進行上報。對於java應用,給大家介紹一個新朋友jmxtrans。
讀取json或yaml格式的配置文件,通過jmx採集java性能指標。支持輸出到Graphite、InfluxDB、RRDTool等。
安裝部署
1.首先下載jmxtrans的RPM包, 地址
2.安裝jdk1.8
yum install -y java-1.8.0-openjdk.x86_64 java-1.8.0-openjdk-devel.x86_64
3.設置JAVA_HOME和PATH環境變量
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.65-0.b17.el6_7.x86_64
export PATH=$JAVA_HOME/bin:/usr/share/jmxtrans/bin:$PATH
4.編寫配置文件
下文是一段測試用的配置,採集的數據會輸出到日誌中顯示。
{
"servers" : [ {
"port": "jmx端口",
"host": "IP地址",
"queries" : [ {
"outputWriters" : [ {
"@class" : "com.googlecode.jmxtrans.model.output.StdOutWriter"
} ],
"obj" : "java.lang:type=Memory",
"attr" : [ "HeapMemoryUsage", "NonHeapMemoryUsage" ]
}, {
"outputWriters" : [ {
"@class" : "com.googlecode.jmxtrans.model.output.StdOutWriter"
} ],
"obj" : "java.lang:name=CMS Old Gen,type=MemoryPool",
"attr" : [ "Usage" ]
}, {
"outputWriters" : [ {
"@class" : "com.googlecode.jmxtrans.model.output.StdOutWriter"
} ],
"obj" : "java.lang:name=ConcurrentMarkSweep,type=GarbageCollector",
"attr" : [ "LastGcInfo" ]
} ],
"numQueryThreads" : 2
} ]
}
5.配置文件編輯完成後,將其放在 /var/lib/jmxtrans/
目錄中
6.啓動jmxtrans
jmxtrans start
jmxtrans會以後臺deamon的形式運行,每隔1分鐘採集一次數據
部署方式
由於jmx是通過網絡連接的,因此JMXtrans的部署方案有2種
-
集中式,在一臺服務器上部署一個JMXtrans,分別連接至所有的Kafka實例,並將數據吐到InfluxDB。爲了減少網絡傳輸,可以考慮部署到InfluxDB的服務器上
-
分佈式,每個Kafka實例部署一個JMXtrans
這裏我們採用了方案2
P.S 如果JMX能夠支持UNIX socket方式連接方案就更完美了。socket連接較TCP連接開銷更小,效率更高,非常適合同一臺服務器上2個進程之間的通信
分析與轉換
由於Kafka的性能數據非常全面,大部分指標已經做了分析了。
類似上述,指標的直方圖,次數,最大最小、標準方差都已經計算好了,因此我們不再對數據再做加工。
這裏只取了每項指標的Mean項(中位數) 做爲指標值寫入InfluxDB當中。
展現
Grafana是一款非常強大的純前端的畫圖軟件,可以說畫什麼圖,動動鼠標就可以配出來。
設置變量模版
支持變量模版,例如下圖,我們將展現的指標所屬的實例定義爲變量
之後在圖表的左上角就可以通過下拉框的方式選擇要查看的實例的圖表,支持多選
支持前端對數據進行加工
例如CPU使用率數據,我們採集到的數據實際是一個計數器,記錄了採集時的CPU時間。
使用率我是這樣定義的, 採集2次
CPU使用率 = (結束數據-開始數據)/採集間隔時間
這裏通過配置的方式實現了數據加工與展現。
最後圖表頁面是這樣一個效果,是不是非常炫酷呢
尾聲
Tomcat、JBoss這類的JAVA應用都支持JMX,下面的還用我說麼?