想要监控Java应用,JMX永远是第一选择。在prometheus监控体系中,jmx_exporter是使用范围十分广的工具。本文对jmx的配置进行一个讲解,主要是对社区文档进行翻译并解释说明。

jmx_exporter 启动

简单说一下启动,官方给出的 jmx_exporter启动命令是:

  1. java -javaagent:./jmx_prometheus_javaagent-0.13.0.jar=8080:config.yaml -jar yourJar.jar

启动完成后即可在 http://localhost:8080/metrics 查看到指标数据。
jmx_exporter是以java agent的模式启动的,那些与JMX远程输出相关的配置(如-Dcom.sun.management.jmxremote.port=1234)其实是没有必要的。jmx_exporter也支持独立启动,然后配置JMX远程通讯端口。
像一些大型项目,启动的形式肯定不是 java -jar,我们需要找到传入执行参数的入口,一般是一些环境配置文件。

jmx_exporter 配置解释

下面是官方给出的jmx_exporter的配置样例:

  1. ---
  2. startDelaySeconds: 0
  3. hostPort: 127.0.0.1:1234
  4. username:
  5. password:
  6. jmxUrl: service:jmx:rmi:///jndi/rmi://127.0.0.1:1234/jmxrmi
  7. ssl: false
  8. lowercaseOutputName: false
  9. lowercaseOutputLabelNames: false
  10. whitelistObjectNames: ["org.apache.cassandra.metrics:*"]
  11. blacklistObjectNames: ["org.apache.cassandra.metrics:type=ColumnFamily,*"]
  12. rules:
  13. - pattern: 'org.apache.cassandra.metrics<type=(\w+), name=(\w+)><>Value: (\d+)'
  14. name: cassandra_$1_$2
  15. value: $3
  16. valueFactor: 0.001
  17. labels: {}
  18. help: "Cassandra metric $1 $2"
  19. type: GAUGE
  20. attrNameSnakeCase: false

这里给出官方配置项解释的翻译,加入了一点我自己的描述:

名称 描述
startDelaySeconds 在处理请求前的启动延迟,单位为秒。在延迟期间,也就是启动前,任何的请求都只会返回空的指标集
hostPort 远程JMX接入的主机与端口号。如果此配置项和jmxurl都没有被设置,则会与本地JVM会话。(以推荐的-javaagent 模式启动,并且没有配置远程JMX,则不用填此配置项。)
username 远程JMX身份认证的用户名
password 远程JMX身份认证的密码
jmxUrl 完整的 JMX URL,若配置了主机和端口则不应配置此项。
ssl 是否开启与JMX的SSL通讯。要配置此项前必须设置一些系统属性:
-Djavax.net.ssl.keyStore=/home/user/.keystore
-Djavax.net.ssl.keyStorePassword=changeit
-Djavax.net.ssl.trustStore=/home/user/.truststore
-Djavax.net.ssl.trustStorePassword=changeit
lowercaseOutputName 是否把指标名称转换为小写,默认为false。
lowercaseOutputLabelNames 是否把标签名称转换为小写,默认为false
whitelistObjectNames 查询对象白名单,默认是所有mBeans对象。不在白名单则不会被查询。支持正则匹配。
blacklistObjectNames 查询对象黑名单,默认无。支持正则匹配。
rules 一个按顺序引用的规则列表,处理过程会在第一条规则匹配上时停止。未匹配上的atrributes则不会被收集。默认以默认格式收集所有指标
pattern 匹配每一个bean attribute(属性)的正则样式。该样式不是锚定的。可以设置正则捕获组用与其他配置项(如上面的样例 name: cassandra$1$2)。默认匹配所有格式。
attrNameSnakeCase 将attribute名称 转换为蛇形格式。例如 anAttrName 转换为 an_attr_name。默认为false
name 指标名。可以引用 pattern中设置的捕获组。如果没有指定则使用默认格式。如果为空,此attribute的处理会停止且没有输出。
value 指标值。静态值和引用pattern捕获组均可。如果没指定则抓取mBean attribute对应的value值。
valueFactor 指标值(或 mBean value)的乘数。多用于秒和毫秒等单位转化
labels 标签名:标签值 形式的键值对。可引用捕获组。使用时必须配置 name 项。如果没有指定并且没有使用默认格式,则不会输出标签。
help 指标的帮助信息,可引用捕获组 。使用时必须配置 name 项。默认为mBean attribute的描述和全名。
type 指标格式,值为 GAUGE, COUNTER 或 UNTYPED. 使用时必须配置 name项,默认为 UNTYPED

输入格式:

  1. domain<beanpropertyName1=beanPropertyValue1, beanpropertyName2=beanPropertyValue2, ...><key1, key2, ...>attrName: value
Part Description
domain Bean对象名. JMX object name 冒号之前的部分。
beanProperyName/Value Bean属性. JMX object name 冒号后的key/values 对。
keyN 如果 Bean有多层嵌套,嵌套的字段会写入这里。
attrName attribute名. 如果是表格式数据,attrName为列名。 如果attrNameSnakeCase 已设置, 会转化为 snake 模式。
value attribute 值

默认的输出格式:

  1. domain_beanPropertyValue1_key1_key2_...keyN_attrName{beanpropertyName2="beanPropertyValue2", ...}: value

Rules 的使用实践

rules的主要功能是进行指标的过滤和清洗。还有一个功能是对value进行转化。prometheus无法接受字符数据,但有时候我们确实需要这个字符串信息,这时候就可以用rules进行配置转化。
下面以一个案例来介绍rules的使用。

jmx的格式为一个json对象,里面是一个包含多个bean对象的数组:

  1. {
  2. "beans":[
  3. {bean},
  4. {bean}
  5. ]
  6. }

下文为我配置hadoop监控时的一个bean对象,实际省略了部分内容

  1. {
  2. "name" : "Hadoop:service=NameNode,name=FSNamesystemState",
  3. "modelerType" : "org.apache.hadoop.hdfs.server.namenode.FSNamesystem",
  4. "PendingReplicationBlocks" : 0,
  5. "PendingReconstructionBlocks" : 0,
  6. "UnderReplicatedBlocks" : 0,
  7. "LowRedundancyBlocks" : 0,
  8. "ScheduledReplicationBlocks" : 0,
  9. "PendingDeletionBlocks" : 0,
  10. "BlockDeletionStartTime" : 1591347343145,
  11. "FSState" : "Operational",
  12. },

其中 “FSState”是HDFS文件系统的状态,有两个值 Safemode(安全模式)和Operational(可使用)。我希望我的监控可以监测到文件系统的状态。可jmx_exporter中确找不到这个指标。因为我的配置文件是空的,jmx_exporter会过滤到所有字符串value,因为prometheus无法接收。因此我需要配置rules将字符串转化为数值型。
首先是需要根据pattern import的格式把指标的输入格式写出来:
Hadoop<>FSState:value
然后用正则表达式进行判断,value含有Safemode 为 0, 含有Operational为1
为了与其他指标统一,我的name的写法与默认输出相同。
最后的配置为:

  1. ---
  2. rules
  3. - pattern: 'Hadoop<service=NameNode, name=FSNamesystemState><>FSState:.*?Safemode.*?'
  4. name: Hadoop_NameNode_FSState
  5. value: 0
  6. - pattern: 'Hadoop<service=NameNode, name=FSNamesystemState><>FSState:.*?Operational.*?'
  7. name: Hadoop_NameNode_FSState
  8. value: 1
  9. - pattern: '.*'

注意到这里我最后加了一个匹配所有指标的正则表达。如果不加的话,最后exporter除了jvm的指标,只会输出在rules中匹配成功的指标。
还有一个十分tricky的点!- pattern: ‘.*’ 必须放在最后。我们回头看看rules的描述,是顺序执行的,每个指标而且完成匹配后就会停止继续匹配。如果把全局匹配放在最前,那所有的指标都会被匹配上,匹配就结束了。但带字符串的被过滤掉了,而且后面的规则也不会生效。那这条指标还是不会出现在jvm_exporter的httpserver上。

此指标在jmx_exporter上的呈现:

# HELP Hadoop_NameNode_FSState Attribute exposed for management (Hadoop<service=NameNode, name=FSNamesystemState><>FSState)
# TYPE Hadoop_NameNode_FSState untyped
Hadoop_NameNode_FSState 1.0

在Grafana里我们可以 用Gauge或 Singlestat试图,使用ValueMapping将数值表达的文字含义呈现出来。

Reference

https://github.com/prometheus/jmx_exporter