写点什么

如何基于 jmx exporter 监控 java 应用

作者:Jaywin
  • 2023-12-19
    广东
  • 本文字数:4858 字

    阅读完需:约 16 分钟

如何基于jmx exporter监控java应用

在现代应用服务架构体系中,监控体系的建设是系统稳定性建设工程中基础且关键的一环。而在 Java 编程语言开发出来的应用服务中,一般是基于 JMX 技术对外提供监控数据的采集入口。


下面我们谈一谈,如何基于 jmx exporter 的方式来监控 Java 应用。不过,首先我们需要明确一些概念。

JMX 是什么

Java Management Extensions(JMX)技术是 Java SE 平台的标准功能,是Java平台上为应用程序、设备、系统等植入管理功能的框架。


它提供了一种简单的、标准的监控和管理资源的方式,对于如何定义一个资源给出了明确的结构和设计模式,主要用于监控和管理 Java 应用程序运行状态、设备和资源信息、Java 虚拟机运行情况等信息JMX 是可以动态的,所以也可以在资源创建、安装、实现时进行动态监控和管理,JDK 自带的 jconsole 就是使用 JMX 技术实现的监控工具。


当使用 JMX 技术时,通常需要定义一个被称为 MBean(Managed Bean)的 Java 对象来表示特定的资源,MBean 是一种通过依赖注入创建的 JavaBean,代表了运行在 Java 虚拟机上的资源。它通过 pull 的方式,去收集如性能、资源使用率、问题信息等关键的统计信息,也通过 push 和 push 的方式来获取或设置应用程序的配置或属性。


这和 SNMP 监控当中 OID 的概念非常类似,每个 MBean 通常都代表了一类资源。而 ObjectName 是用于唯一标识 MBean 的对象名,它的标识方法是这样的一种形式:


domain:beanpropertyName1=beanPropertyValue1
复制代码


它是由一个域(domain)和键值组成的标识符,用于在 JMX 中注册和检索 MBean。ObjectName 提供了一种层次结构和规范,确保 MBean 的唯一性和可识别性。


因此,我们可以把资源信息注册到 MBean Server 以对外提供服务,MBean Server 充当对外提供服务,对内管理 MBean 资源的代理角色,以让 MBean 的资源管理和 MBean Server 代理完全独立开,使之可以自由地控制 MBean 资源信息。并使用 ObjectName 去获取和管理特定的 MBean 资源。


除此之外,JMX 不仅仅用于本地管理,JMX Remote API 还为 JMX 添加了远程功能,使其可以通过网络远程监视和管理应用程序。

优点

JMX 技术为 Java 开发者提供了一种简单、灵活、标准的方式来监测 Java 应用程序,得益于相对独立的架构设计,使 JMX 可以平滑的集成到各种监控系统之中。


下面列举几项 JMX 的具体优点:


  1. 开箱即用的监控功能,JMX 是 Java SE 的标准部分,提供了资源管理、服务托管、远程监控等管理基础功能,都可以直接启用。

  2. JMX 技术提供了一种通用的、标准的资源、系统、应用程序、网络的管理方式,不仅可以本地使用、远程使用;还可以扩展到其他场景,如 Java EE 应用等。

  3. JMX 技术提供了对 JVM 状态的监测功能,JMX 已经内置了对 JVM 的监测功能,并且可以监控和管理 JVM,十分方便。

  4. JMX 架构设计优秀,组件化的设计可以自由的扩展。

  5. JMX 技术严格遵守 Java 现有规范如 JNDI 规范。

  6. JMX 可以自由的与其他管理解决方案集成,得益于开放的 JMX API,可以通过 web 服务管理 JMX 中的资源。

技术架构

JMX 技术架构主要有资源管理(MBean/MXBean)模块,资源代理模块(MBean Server),远程管理模块(Remote API)组成 :



资源管理在架构中标识为资源探测层(Probe Level),在 JMX 中, 使用 MBeanMXBean 来表示一个资源(下面简称 MBean),访问和管理资源也都是通过 MBean,所以 MBean 往往包含着资源的属性和操作方法


JMX 已经对 JVM 进行了多维度资源检测,所以可以轻松启动 JMX 代理来访问内置的 JVM 资源检测,从而通过 JMX 技术远程监控和管理 JVM。


下面列举 JMX 对 JVM 的资源检测类,都可以直接使用:



因此,我们可以通过 jmx exporter,通过指定 MBean 中的 ObjectName 的方式,去抓取由 JMX 对外输出的指标数据。


除了上表提供的通用 Mbean,那如何获取自定义的 Mbean?当安装好 JDK 环境后,即可通过 jconsole 本地或远程连接到 jmx 端口,我们就可以看到该应用暴露出来的所有 MBeans。我们可以在下面的演示中看到这一过程。

jmx exporter

jmx exporter 作为 Java 代理运行,它是一个可配置的,收集、抓取和暴露 JMX 目标下的 MBeans 的采集器。它作为 Java 代理运行,暴露一个 HTTP 服务器并提供本地的 JVM 指标数据。并且,它也支持 Basic 认证功能以确保指标数据的访问安全性。


具体的详细介绍和使用可参考官方文档.


而这里我们以 TongWeb 为监控对象,重点描述如何一步一步去获取和配置 TongWeb 的 jmx exporter 配置文件,并抓取到相应的指标数据。我们会描述如何基于正则表达式模式匹配的方式,去为 jmx exporter 采集上来的原始指标数据进行简单的加工,转换以生成合适的指标。

开启 tongweb 的 jmx 端口

步骤略。

暴露原生指标数据

在 jmx exporter 的配置文件中,指定监控目标:


# config.yml---
hostPort: $jmxHost:$jmxPortattrNameSnakeCase: true # 将JMX属性(MBean属性)的名称转换为蛇形命名法lowercaseOutputName: true # 将输出的指标名称(Metrics name)转换为小写 lowercaseOutputLabelNames: true # 将输出的标签名称转换为小写username: xxxpassword: xxx
复制代码


在 jmx exporter 的配置文件中,是通过正则表达式模式匹配的规则去过滤出目标指标的,因此如何编写匹配规则是在配置抓取指标时非常关键的步骤。一个最简单的匹配规则如下:


rules:- pattern: ".*"
复制代码


它表示直接输出所有的指标数据,不做任何处理。在本次示例当中,当我们以这个配置启动 exporter 后,输出的结果如下:


# HELP java_lang_garbagecollector_lastgcinfo_gcthreadcount CompositeType for GC info for PS Scavenge java.lang:name=PS Scavenge,type=GarbageCollector,attribute=GcThreadCount# TYPE java_lang_garbagecollector_lastgcinfo_gcthreadcount untypedjava_lang_garbagecollector_lastgcinfo_gcthreadcount{name="PS Scavenge",} 4.0java_lang_garbagecollector_lastgcinfo_gcthreadcount{name="PS MarkSweep",} 4.0# HELP config_monitorconfig_twserver_persistentenabled Introspected attribute persistentEnabled config:name=MonitorConfig[TWServer],type=null,attribute=persistentEnabled# TYPE config_monitorconfig_twserver_persistentenabled untypedconfig_monitorconfig_twserver_persistentenabled{parent="/Tongweb/Server/MonitorService",} 0.0# HELP config_virtualhost_server_status Introspected attribute status config:name=VirtualHost[server],type=null,attribute=status
....
复制代码


这里摘取一段指标作简要说明:


# HELP java_lang_garbagecollector_lastgcinfo_gcthreadcount CompositeType for GC info for PS Scavenge java.lang:name=PS Scavenge,type=GarbageCollector,attribute=GcThreadCount# TYPE java_lang_garbagecollector_lastgcinfo_gcthreadcount untypedjava_lang_garbagecollector_lastgcinfo_gcthreadcount{name="PS Scavenge",} 4.0java_lang_garbagecollector_lastgcinfo_gcthreadcount{name="PS MarkSweep",} 4.0
复制代码


  • HELP:表示 MBeans 的 ObjectName 为:java.lang:name=PS Scavenge,type=GarbageCollector,attribute=GcThreadCount

  • TYPE:标明了指标的类型,此处表示未指定类型

  • 指标:原生指标数据,包含指标名、标签和指标值


这段原始指标数据无法直接作为 Prometheus 监控系统的抓取对象,因为某些指标名中可能嵌入了变量,比如下面这段:


# HELP com_tongweb_hulk_pool_fkds_activeconnections com.tongweb.hulk:name=null,type=Pool (fkDS),attribute=ActiveConnections# TYPE com_tongweb_hulk_pool_fkds_activeconnections untypedcom_tongweb_hulk_pool_fkds_activeconnections 0.0
复制代码


指标名com_tongweb_hulk_pool_fkds_activeconnections 中的fkds实际上是 jdbc 连接池中的一个数据库实例名,而这个名称应该作为指标的标签附加,以表示不同的指标维度。


编写配置文件的目的就是指定要过滤出来的 MBean 资源对象,并对其指标名加工处理,重写为合适的指标名,附加正确的标签和定义合适的指标值类型。


接下来的问题就是,如何编写合适的匹配规则。

编写模式匹配规则

在 jmx exporter 中,主要基于以下格式去识别 MBean 资源:


domain<beanpropertyName1=beanPropertyValue1, beanpropertyName2=beanPropertyValue2, ...><key1, key2, ...>attrName: value
复制代码


首先,我们基于 jconsole 连接到 JVM 上,查看它的所有 MBean 资源



而后,我们找到要编写的原始指标数据对应的 MBean 属性:


# HELP com_tongweb_hulk_pool_fkds_activeconnections com.tongweb.hulk:name=null,type=Pool (fkDS),attribute=ActiveConnections# TYPE com_tongweb_hulk_pool_fkds_activeconnections untypedcom_tongweb_hulk_pool_fkds_activeconnections 0.0
复制代码



注意这里的类型如果是简单数据类型,那么表示 key 值为空,使用<>表示。


于是,这段配置可以这样写:


  - pattern: '^com.tongweb.hulk<type=Pool \((.+)\)><>(.*): (\d+)'    name: jdbc_pool_$2    value: $3    labels:      name: $1    type: GAUGE
复制代码


  • pattern: '^com.tongweb.hulk<type=Pool \((.+)\)><>(.*): (\d+)':过滤出 com.tongweb.hulk 这个域下的资源,类型为Pool (.+),并且 key 为空(用<>表示)的所有属性。注意:当 key 为空时,<>不可省略。也就意味着,一定要符合domain<><>: value这种格式。

  • name:指标名修改为jdbc_pool_属性名

  • value:指标值

  • labels:将数据库实例名作为标签附加到指标名下,表示不同维度

  • type:表示该指标类型为GAUGE


转换后的结果如下:


# HELP jdbc_pool_activeconnections com.tongweb.hulk:name=null,type=Pool (fkDS),attribute=ActiveConnections# TYPE jdbc_pool_activeconnections gaugejdbc_pool_activeconnections{name="fkDS",} 0.0
复制代码


另外,有些指标数据的 key 不为空,比如:



它的原始指标数据如下:


# HELP java_lang_garbagecollector_lastgcinfo_duration CompositeType for GC info for PS Scavenge java.lang:name=PS Scavenge,type=GarbageCollector,attribute=duration# TYPE java_lang_garbagecollector_lastgcinfo_duration untypedjava_lang_garbagecollector_lastgcinfo_duration{name="PS Scavenge",} 9.0java_lang_garbagecollector_lastgcinfo_duration{name="PS MarkSweep",} 378.0
# HELP java_lang_garbagecollector_lastgcinfo_gcthreadcount CompositeType for GC info for PS Scavenge java.lang:name=PS Scavenge,type=GarbageCollector,attribute=GcThreadCount# TYPE java_lang_garbagecollector_lastgcinfo_gcthreadcount untypedjava_lang_garbagecollector_lastgcinfo_gcthreadcount{name="PS Scavenge",} 4.0java_lang_garbagecollector_lastgcinfo_gcthreadcount{name="PS MarkSweep",} 4.0
复制代码


这表示lastgcinfo下有多个属性:durationgcthreadcount


我们仅需要获取duration,表示 gc 的持续时间


对应的匹配规则配置:


  - pattern: 'java.lang<type=GarbageCollector, name=[^>]+><LastGcInfo>duration: (\d+)'    name: jvm_gc_duration_seconds    value: $1    type: GAUGE
复制代码


应用后的结果如下:


# HELP jvm_gc_duration_seconds CompositeType for GC info for PS Scavenge java.lang:name=PS Scavenge,type=GarbageCollector,attribute=duration# TYPE jvm_gc_duration_seconds gaugejvm_gc_duration_seconds 9.0
复制代码

打开 basic 认证(可选)

jmx exporter 提供了 basic 认证,它要求用户在访问暴露的数据时键入用户名和密码,以提供简单的身份安全认证的手段。我们以 SHA-256 加密算法为例,介绍如何启用认证。


SHA-256 example using a salted password SHA-256(<salt>:<password>) with a password of secret


我们可以按以下步骤生成加密 hash 和 salt


salt=`openssl rand -base64 12`echo -n "$salt:mypassWord" | sha256sum
复制代码


生成后配置如下:


httpServer:  authentication:    basic:      username: Prometheus      passwordHash: 4af63316598b5fa7f1cc9f1f359fb285bb5f1ffad8f53a9a293b9aa601f80040      algorithm: SHA-256      salt: VIJU4CARFmFmAUvU 
复制代码


注意密码长度要大于 8 个字符,否则会无法通过认证。


发布于: 刚刚阅读数: 7
用户头像

Jaywin

关注

还未添加个人签名 2022-05-29 加入

还未添加个人简介

评论

发布
暂无评论
如何基于jmx exporter监控java应用_Prometheus_Jaywin_InfoQ写作社区