架构

JMX

师成师成· 更新于 2026-09-28· 阅读 28 分钟· 0 次阅读

登录后可跨设备保存划线和私人笔记登录

JMX

Camel 对 JMX 管理提供了可选支持,相关功能位于 camel-management 和 camel-management-api 这两个 JAR 包中。

使用 JMX 管理 Apache Camel

当类路径中包含 camel-management JAR 时,Camel 会启用 JMX 插桩代理。启用后,Camel 运行时会创建 MBean 管理对象并将其注册到 VM 中的 MBeanServer 实例上。这样,Camel 用户就能即时了解 Camel 路由的运行状况,细粒度可追溯到单个处理器级别。

高层支持的管理对象类型包括:

大多数管理对象除了提供性能计数器属性外,还暴露了生命周期操作。

禁用或启用 Camel JMX

只有当类路径中包含 camel-management JAR 时,Camel 中的 JMX 才会启用。要快速启用或禁用 JMX,只需在类路径中添加或移除该 JAR 即可。

也可以通过配置来启用或禁用 JMX,具体说明如下。

  • JVM
  • Spring XML
  • Java
  • 应用属性

你可以通过设置如下的 Java VM 系统属性来禁用 JMX 插桩代理:

-Dorg.apache.camel.jmx.disabled=true

或者,在 Spring XML 配置中的 camelContext 元素内添加一个 jmxAgent 元素:

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
  <jmxAgent id="agent" disabled="true"/>
    ...
</camelContext>

在 Java 中,你可以直接在 CamelContext 上禁用 JMX,方式如下:

CamelContext camel = new DefaultCamelContext();
camel.disableJMX();

你也可以在 application.properties 中禁用 JMX,例如在使用 Spring Boot 时。

camel.main.jmxEnabled = false

Camel JMX 配置选项

Camel JMX 可以通过以下选项进行配置。

选项默认值说明
id必填 JMX 代理名称
usePlatformMBeanServertrue是否使用 JVM 中的 MBeanServer。
mbeanServerDefaultDomainorg.apache.camelMBeanServer 的默认 JMX 域
mbeanObjectDomainNameorg.apache.camel所有对象名称将使用的 JMX 域
mbeansLevelDefault配置注册 MBean 的级别。详见 仅为特定资源注册 MBean 一节。
onlyRegisterProcessorWithCustomIdfalse如果启用此选项,则只会注册设置了自定义 id 的处理器。这使你能够在 JMX 控制台中过滤掉不需要的处理器。
statisticsLevelDefault配置是否为 MBean 启用性能统计的级别。详见 配置性能统计的粒度级别 一节。
includeHostNamefalse是否在 MBean 命名中包含主机名。
useHostIPAddressfalse创建远程连接器时,服务 URL 中使用主机名还是 IP 地址。默认使用主机名。
loadStatisticsEnabledfalse是否启用负载统计(通过每个 CamelContext 的后台线程收集负载统计信息)。
endpointRuntimeStatisticsEnabledtrue是否启用端点运行时统计(收集每个入站和出站端点的运行时使用情况)。
masktrue一个标志,指示是否从 MBean 名称和属性中移除检测到的敏感信息(例如密码)。
updateRouteEnabledfalse是否允许通过 JMX 使用 ManagedRouteMBean 在运行时更新路由。默认禁用,但可以为开发和故障排查目的启用,例如通过 JMX 及其他工具更新正在运行的 Camel 中的路由。
每个选项也可以作为 JVM 系统属性指定,例如 -Dorg.apache.camel.jmx.useHostIPAddress=true。

仅为特定资源注册 MBean

Camel 启动时会自动为上下文、路由和处理器注册 MBean。不过,你可以指定一个级别来控制是否在启动时注册 MBean。这些级别包括:

  • Default — Camel 将为上下文、所有路由和处理器注册 MBean。
  • RoutesOnly — Camel 将为上下文和所有路由注册 MBean(不为任何处理器注册)。
  • ContextOnly — Camel 将仅为上下文注册 MBean(不为任何路由或处理器注册)。

为通过路由模板、Kamelet 创建的新路由注册新的 MBean

Camel 提供以下设置来控制何时注册 MBean。

选项默认值说明
registerAlwaysfalse若启用,则始终注册 MBean。
registerNewRoutestrue若启用,则在 CamelContext 启动之后添加新路由时,也会为该路由注册 MBean。
registerRoutesCreateByKameletfalse若启用,则添加由 Kamelet 创建的路由时,也会为该路由注册 MBean。
registerRoutesCreateByTemplatetrue若启用,则添加由路由模板(非 Kamelet,参见上面的选项)创建的路由时,也会为该路由注册 MBean。

默认情况下,Camel 会为启动时配置的所有路由自动注册 MBean。registerNewRoutes 选项用于控制是否也为后续添加的新路由注册 MBean。例如,如果你在添加和删除无需管理的临时路由,则可以禁用此功能。

自 Camel 4.5 起,新增了用于配置由路由模板或 Kamelet 创建的路由是否注册为 MBean 的选项。默认情况下,Kamelet 现在是禁用的,其意图是将 Kamelet 视为一个组件,而不是一组额外的路由和处理器 MBean——这些 MBean 对管理和监控来说基本是不必要的。可以将选项 registerRoutesCreateByKamelet 设置为 true 以启用 MBean,这与 Camel 4.4 或更早版本的行为一致。另一方面,由路由模板(而非 Kamelet)创建的路由默认是启用的。

但是,在使用 registerAlways 选项时要谨慎,尤其是与动态 EIP 模式结合使用时,例如收件人列表,这些模式具有唯一的端点。这可能会导致注册表中关联服务/生产者的 MBean 数量不断增加,从而造成系统性能下降。请记住,MBean 并非轻量级对象,它会占用内存。

为什么我的处理器没有出现在 JMX 中?

并非所有处理器都是受管的,因此并非所有处理器都能在 JMX 中显示,例如在浏览 JConsole 时。

Processor 必须实现 org.apache.camel.Service 才能被管理。

所有以 Processor 方式实现的 EIP 都是 Service。

您的自定义 Processor 可以实现 Service 或继承 ServiceSupport,需要在 JMX 中暴露的信息可以使用 camel-management JAR 中的以下注解进行标记:

  • @ManagedResource - 用于类级别的一般信息
  • @ManagedAttribute - 用于 JMX 属性
  • @ManagedOperation - 用于 JMX 操作

管理命名模式

您可以配置 Camel 创建的 MBean 名称的命名模式。该模式用作 ObjectName 的一部分,即域名之后的键。

默认情况下,Camel 将为 ManagedCamelContextMBean 使用如下形式的 MBean 名称:

org.apache.camel:context=camel-1,type=context,name=camel-1

如果在 CamelContext 上配置了名称,那么该名称同样会成为 ObjectName 的一部分。例如,如果我们有:

Spring XML

<camelContext id="myCamel" ...>

或者在 application.properties 中

camel.main.name = myCamel

那么,MBean 名称将如下所示:

org.apache.camel:context=myCamel,type=context,name=myCamel

如果 JVM 中存在命名冲突,例如已经存在同名的 MBean,Camel 会通过计数器在 JMXMBeanServer 中寻找一个新的可用名称,自动尝试解决该问题。例如,计数器会被追加到名称之后,从而生成诸如 myCamel-1 这样的 ObjectName:

org.apache.camel:context=myCamel-1,type=context,name=myCamel

命名模式

之所以可行,是因为 Camel 默认使用一种命名模式,该模式支持以下占位符:

  • #camelId# = CamelContext 的 id(例如其名称)
  • #name# - 与 #camelId# 相同
  • #counter# - 递增的计数器

如果在 JMXMBeanServer 中出现命名冲突,Camel 会自动回退,在模式中使用 #counter# 来解决这个问题。因此,此时将使用如下模式:#name#-#counter#

如果你设置了显式的命名模式,则始终使用该模式,而不会使用上述默认模式。

这样我们就可以非常方便地完全掌控 Registry 中 CamelContext 的 id 以及 JMXMBeanRegistry 中 JMX MBean 的命名。

因此,如果我们希望显式命名 CamelContext,并使用固定不变的 MBean 名称(即不带计数器),那么可以使用 managementNamePattern 属性:

<camelContext id="myCamel" managementNamePattern="#name#">

这也可以在 application.properties 中配置:

camel.main.jmxManagementNamePattern = #name#

那么 MBean 名称将始终如下:

org.apache.camel:context=myCamel,type=context,name=myCamel

在 Java 中,可以按如下方式配置 managementNamePattern:

context.getManagementNameStrategy().setNamePattern("#name#");

配置性能统计

你可以在 Camel 启动时设置一个级别,用于决定是否启用性能统计。级别如下:

  • Default — Camel 将同时为路由和处理器启用统计(细粒度)。
  • Extended — 与默认级别相同,但在运行时会收集额外的统计信息,例如端点的细粒度使用情况等。
  • RoutesOnly — Camel 只为路由启用统计(粗粒度)。
  • Off — Camel 不使用任何统计。

启用统计是什么意思?

启用统计意味着 Camel 将针对相应的 MBean 进行细粒度的性能统计。你可以看到多种统计信息,例如完成/失败的交换数量、最近/总计/最小/最大/平均处理时间、首次/最近一次失败时间等。

  • Java
  • Spring XML
  • Application Properties
// only enable routes when Camel starts
context.getManagementStrategy().setStatisticsLevel(ManagementStatisticsLevel.RoutesOnly);
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <jmxAgent id="agent" statisticsLevel="RoutesOnly"/>
 ...
</camelContext>
camel.main.jmxManagementStatisticsLevel = RoutesOnly

性能负载统计

可以包含 CamelContext 和 Route MBean 的负载统计数据。这些统计信息基于在途交换(in-flight exchanges)的数量,反映 1、5 和 15 分钟时间段内的平均负载。这与 Unix 系统上的负载统计类似。

可以通过 application.properties 之类的配置启用负载统计,例如:

camel.main.loadStatisticsEnabled = true

消息大小统计

可以按端点包含消息大小统计信息。这些统计信息会跟踪入站(IN)和出站(OUT)端点上消息正文与消息头的最小、最大和平均大小。

你可以从 application.properties 中启用消息大小统计:

camel.main.messageSizeEnabled = true
camel.main.jmxManagementStatisticsLevel = Extended

有关更多信息,请参阅消息大小。

隐藏敏感信息

默认情况下,Camel 会在 JMX 中注册 MBean,例如使用 URI 配置的端点。在这种配置中,可能包含密码等敏感信息。

这将对含有 password、passphrase 等选项的 URI 进行脱敏,并使用 xxxxxx 作为替换值。

在自定义组件中对 JMX 属性进行脱敏

在实现自定义 Camel 组件时,可以使用 @ManagedAttribute 和 @ManagedOperation 注解标记需要脱敏的 JMX 属性。

mask 属性可以设置为 true,表示该 JMX 属性/操作的结果应被脱敏(前提是已在 JMX 代理上启用,如上所述)。

例如,在 camel-core 的默认托管端点 org.apache.camel.api.management.mbean.ManagedEndpointMBean 中,我们声明了 EndpointUri JMX 属性需要脱敏:

@ManagedAttribute(description = "Endpoint URI", mask = true)
String getEndpointUri();

远程暴露 JMX 指标

在本地运行应用时,你可以使用任何 JMX 客户端(如 jconsole)访问该进程及其暴露的统计数据。但你可能希望远程暴露这些指标,以便任何远程进程都能访问:远程暴露 JMX 指标。

请务必为生产工作负载正确保护 JMX 服务的访问。

如何使用 Java Agent

使用 JMX 原生协议暴露指标并不总是可行的(例如由于防火墙限制、安全性等原因)。在这种情况下,你可以借助兼容 JSR 160 的 Java Agent(例如 Jolokia),其目标是将 JMX 接口适配到基于 HTTP 的协议上。通过这种方式,你可以在运行应用时挂载一个 Java Agent,由它负责通过 HTTP 暴露 JMX。例如:

java -javaagent:jsr160-javaagent.jar -jar my-camel-app.jar

将暴露某些端点(取决于具体实现),从而让你与 JMX 进行交互。

根据不同的实现,你需要提供不同的 agent 配置。例如,如果你运行的是 Jolokia agent,那么你需要运行以下配置,以暴露一个普通的、非安全的 HTTP 服务:

java -javaagent:jolokia-agent-jvm-2.1.1-javaagent.jar=protocol=http,useSslClientAuthentication=false,discoveryEnabled=false,host=*,extendedClientCheck=false -jar my-camel-app.jar

自那时起,你便可以通过以下方式访问该服务:

$ curl http://localhost:8778/jolokia/list/org.apache.camel | jq | more
{
  "request": {
    "path": "org.apache.camel",
    "type": "list"
  },
  "value": {
    "context=camel-1,name=\"platform-http\",type=components": {
      "op": {
        "getCamelId": {
          "args": [],
          "ret": "java.lang.String",
          "desc": "CamelId"
        },
        "isHealthCheckSupported": {
          "args": [],
          "ret": "boolean",
          "desc": "HealthCheckSupported"
        },
        "getComponentName": {
          "args": [],
          "ret": "java.lang.String",
          "desc": "ComponentName"
        },
...

每种代理实现可能会提供不同的方式来获取各类端点并对其执行操作。

对于生产工作负载,请务必确保 HTTP 服务的访问安全,具体请参阅相应的代理配置文档。

评论

登录后参与评论

正在加载评论…