JMX 支持

Spring Integration 提供通道适配器,用于接收和发布 JMX 通知。

项目需要此依赖项

  • Maven

  • Gradle

<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-jmx</artifactId>
    <version>7.0.0</version>
</dependency>
compile "org.springframework.integration:spring-integration-jmx:7.0.0"

入站通道适配器允许轮询 JMX MBean 属性值,而出站通道适配器允许调用 JMX MBean 操作。

通知监听通道适配器

通知监听通道适配器需要 JMX `ObjectName`,用于发布通知的 MBean,此监听器应注册到该 MBean。一个非常简单的配置可能如下所示:

<int-jmx:notification-listening-channel-adapter id="adapter"
    channel="channel"
    object-name="example.domain:name=publisher"/>
`notification-listening-channel-adapter` 在启动时向 `MBeanServer` 注册,默认的 bean 名称是 `mbeanServer`,这恰好与使用 Spring 的 `` 元素时生成的 bean 名称相同。如果需要使用不同的名称,请务必包含 `mbean-server` 属性。

该适配器还可以接受对 `NotificationFilter` 的引用和一个“回执”对象,以提供随每个通知一起传递的上下文。这两个属性都是可选的。在前面的示例基础上,包含这些属性以及一个显式的 `MBeanServer` bean 名称,会产生以下示例:

<int-jmx:notification-listening-channel-adapter id="adapter"
    channel="channel"
    mbean-server="someServer"
    object-name="example.domain:name=somePublisher"
    notification-filter="notificationFilter"
    handback="myHandback"/>

通知监听通道适配器是事件驱动的,并直接注册到 `MBeanServer`。它不需要任何轮询器配置。

对于此组件,`object-name` 属性可以包含对象名称模式,例如 `org.something:type=MyType,name=*`。在这种情况下,适配器会从所有对象名称与模式匹配的 MBean 接收通知。此外,`object-name` 属性可以包含一个 SpEL 引用,指向一个对象名称模式的 ``,如下例所示:

<jmx:notification-listening-channel-adapter id="manyNotificationsAdapter"
    channel="manyNotificationsChannel"
    object-name="#{patterns}"/>

<util:list id="patterns">
    <value>org.foo:type=Foo,name=*</value>
    <value>org.foo:type=Bar,name=*</value>
</util:list>

当启用 DEBUG 级别日志记录时,会记录找到的 MBean 的名称。

通知发布通道适配器

通知发布通道适配器相对简单。它只需要配置中的 JMX 对象名称,如下例所示:

<context:mbean-export/>

<int-jmx:notification-publishing-channel-adapter id="adapter"
    channel="channel"
    object-name="example.domain:name=publisher"/>

它还需要在上下文中存在一个 `MBeanExporter`。这就是为什么在前面的示例中也显示了 `` 元素。

当消息发送到此适配器的通道时,通知会从消息内容创建。如果有效负载是 `String`,它将作为通知的 `message` 文本传递。任何其他有效负载类型都将作为通知的 `userData` 传递。

JMX 通知也有一个 `type`,它应该是一个点分隔的 `String`。有两种方法可以提供 `type`。优先级始终赋予与 `JmxHeaders.NOTIFICATION_TYPE` 键关联的消息头值。或者,您可以在配置中提供一个备用 `default-notification-type` 属性,如下例所示:

<context:mbean-export/>

<int-jmx:notification-publishing-channel-adapter id="adapter"
    channel="channel"
    object-name="example.domain:name=publisher"
    default-notification-type="some.default.type"/>

属性轮询通道适配器

当您需要定期检查通过 MBean 作为受管属性可用的某些值时,属性轮询通道适配器非常有用。您可以以与 Spring Integration 中任何其他轮询适配器相同的方式配置轮询器,或者您可以依赖默认轮询器。`object-name` 和 `attribute-name` 是必需的。`MBeanServer` 引用也是必需的。但是,默认情况下,它会自动检查名为 `mbeanServer` 的 bean,与前面描述的通知监听通道适配器相同。以下示例展示了如何使用 XML 配置属性轮询通道适配器:

<int-jmx:attribute-polling-channel-adapter id="adapter"
    channel="channel"
    object-name="example.domain:name=someService"
    attribute-name="InvocationCount">
        <int:poller max-messages-per-poll="1" fixed-rate="5000"/>
</int-jmx:attribute-polling-channel-adapter>

树状轮询通道适配器

树状轮询通道适配器查询 JMX MBean 树,并发送一个消息,其有效负载是与查询匹配的对象图。默认情况下,MBeans 映射到基本类型和简单对象,例如 `Map`、`List` 和数组。这样做可以进行简单的转换,例如转换为 JSON。`MBeanServer` 引用也是必需的。但是,默认情况下,它会自动检查名为 `mbeanServer` 的 bean,与前面描述的通知监听通道适配器相同。以下示例展示了如何使用 XML 配置树状轮询通道适配器:

<int-jmx:tree-polling-channel-adapter id="adapter"
    channel="channel"
    query-name="example.domain:type=*">
        <int:poller max-messages-per-poll="1" fixed-rate="5000"/>
</int-jmx:tree-polling-channel-adapter>

前面的示例包含了所选 MBean 上的所有属性。您可以通过提供一个配置了适当过滤器的 `MBeanObjectConverter` 来过滤属性。您可以使用 `converter` 属性提供对 bean 定义的引用,或者您可以使用内部 `` 定义。Spring Integration 提供了一个 `DefaultMBeanObjectConverter`,它可以在其构造函数参数中接受一个 `MBeanAttributeFilter`。

Spring Integration 提供了两个标准过滤器。`NamedFieldsMBeanAttributeFilter` 允许您指定要包含的属性列表。`NotNamedFieldsMBeanAttributeFilter` 允许您指定要排除的属性列表。您还可以实现自己的过滤器。

操作调用通道适配器

操作调用通道适配器允许消息驱动地调用 MBean 公开的任何托管操作。每次调用都需要被调用的操作名称和目标 MBean 的对象名称。这两者都必须通过适配器配置或通过 `JmxHeaders.OBJECT_NAME` 和 `JmxHeaders.OPERATION_NAME` 消息头明确提供,分别如下所示:

<int-jmx:operation-invoking-channel-adapter id="adapter"
    object-name="example.domain:name=TestBean"
    operation-name="ping"/>

然后,适配器只需要能够发现 `mbeanServer` bean。如果需要不同的 bean 名称,则提供带有引用的 `mbean-server` 属性。

消息的有效负载映射到操作的参数(如果有)。具有 `String` 键的 `Map` 类型有效负载被视为名称/值对,而 `List` 或数组则作为简单的参数列表传递(没有显式参数名称)。如果操作需要单个参数值,则有效负载可以表示该单个值。此外,如果操作不需要参数,则有效负载将被忽略。

如果您希望公开一个通道,用于调用不需要包含头的单个通用操作,那么最后一个选项效果很好。

操作调用出站网关

与操作调用通道适配器类似,Spring Integration 还提供了一个操作调用出站网关,当处理需要返回值而非空操作时,您可以使用它。返回值作为消息有效负载发送到网关指定的 `reply-channel`。以下示例展示了如何使用 XML 配置操作调用出站网关:

<int-jmx:operation-invoking-outbound-gateway request-channel="requestChannel"
   reply-channel="replyChannel"
   object-name="o.s.i.jmx.config:type=TestBean,name=testBeanGateway"
   operation-name="testWithReturn"/>

如果您不提供 `reply-channel` 属性,则回复消息将发送到由 `MessageHeaders.REPLY_CHANNEL` 头标识的通道。该头通常由消息流的入口点(例如任何网关组件)自动创建。但是,如果消息流是通过手动创建 Spring Integration 消息并直接发送到通道而启动的,则必须明确指定消息头或使用 `reply-channel` 属性。

MBean 导出器

当配置了 `IntegrationMBeanExporter` 时,Spring Integration 组件本身可以作为 MBean 公开。要创建 `IntegrationMBeanExporter` 实例,请定义一个 bean 并提供对 `MBeanServer` 和域名称(如果需要)的引用。您可以省略域,在这种情况下,默认域是 `org.springframework.integration`。以下示例展示了如何声明 `IntegrationMBeanExporter` 实例和关联的 `MBeanServer` 实例:

<int-jmx:mbean-export id="integrationMBeanExporter"
            default-domain="my.company.domain" server="mbeanServer"/>

<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
    <property name="locateExistingServerIfPossible" value="true"/>
</bean>

MBean 导出器与 Spring 核心中提供的导出器是正交的。它注册消息通道和消息处理器,但不注册自身。您可以使用标准 `` 标签来公开导出器本身(以及 Spring Integration 中的某些其他组件)。导出器附加了一些度量指标,例如处理器的数量和队列中消息的数量。

它还有一个有用的操作,如有序关闭托管操作中所述。

Spring Integration 4.0 引入了 `@EnableIntegrationMBeanExport` 注解,允许在 `@Configuration` 类级别方便地配置一个类型为 `IntegrationMBeanExporter` 的默认 `integrationMbeanExporter` bean,并提供一些有用的选项。以下示例展示了如何配置此 bean:

@Configuration
@EnableIntegration
@EnableIntegrationMBeanExport(server = "mbeanServer", managedComponents = "input")
public class ContextConfiguration {

	@Bean
	public MBeanServerFactoryBean mbeanServer() {
		return new MBeanServerFactoryBean();
	}
}

如果您需要提供更多选项或拥有多个 `IntegrationMBeanExporter` bean(例如用于不同的 MBean Server 或避免与标准 Spring `MBeanExporter` 冲突——例如通过 `@EnableMBeanExport`),您可以将 `IntegrationMBeanExporter` 配置为通用 bean。

MBean 对象名称

应用程序中的所有 `MessageChannel`、`MessageHandler` 和 `MessageSource` 实例都由 MBean 导出器包装,以提供管理和监控功能。下表列出了每种组件类型生成的 JMX 对象名称:

表1. MBean 对象名称
组件类型 对象名称

MessageChannel

 `o.s.i:type=MessageChannel,name=<channelName>`

MessageSource

 `o.s.i:type=MessageSource,name=<channelName>,bean=<source>`

MessageHandler

 `o.s.i:type=MessageSource,name=<channelName>,bean=<source>`

源和处理器的对象名称中的 `bean` 属性采用下表中的值之一:

表2. bean 对象名称部分
Bean 值 描述

endpoint

如果存在,则为 enclosing endpoint 的 bean 名称(例如 ``)

匿名

表示 enclosing endpoint 没有用户指定的 bean 名称,因此 JMX 名称是输入通道名称。

内部

对于众所周知的 Spring Integration 默认组件

handler/source

以上都不是。回退到被监控对象(处理器或源)的 `toString()` 方法

您可以通过在 `object-name-static-properties` 属性中提供对 `Properties` 对象的引用来向对象名称附加自定义元素。

此外,从 Spring Integration 3.0 开始,您可以通过设置 `object-naming-strategy` 属性来使用自定义的 `ObjectNamingStrategy`。这样做可以更好地控制 MBean 的命名,例如将所有集成 MBean 分组到“Integration”类型下。以下示例展示了一种可能的自定义命名策略实现:

public class Namer implements ObjectNamingStrategy {

	private final ObjectNamingStrategy realNamer = new KeyNamingStrategy();
	@Override
	public ObjectName getObjectName(Object managedBean, String beanKey) throws MalformedObjectNameException {
		String actualBeanKey = beanKey.replace("type=", "type=Integration,componentType=");
		return realNamer.getObjectName(managedBean, actualBeanKey);
	}

}

`beanKey` 参数是一个 `String`,它包含标准对象名称,以 `default-domain` 开头并包含任何额外的静态属性。前面的示例将标准 `type` 部分移到 `componentType`,并将 `type` 设置为“Integration”,从而可以在一次查询中选择所有集成 MBean:`my.domain:type=Integration,*`。这样做还将 bean 分组到域下的一个树条目中,例如在 VisualVM 等工具中。

默认命名策略是 `MetadataNamingStrategy`。导出器将 `default-domain` 传播到该对象,以便在解析 bean 键失败时生成备用对象名称。如果您的自定义命名策略是 `MetadataNamingStrategy`(或其子类),则导出器不会传播 `default-domain`。您必须在您的策略 bean 上配置它。

从版本 5.1 开始,任何 bean 名称(由对象名称中的 `name` 键表示)如果包含 Java 标识符中不允许的任何字符(或句点 `.`),都将被引用。

JMX 改进

4.2 版本引入了一些重要的改进,代表了框架中 JMX 支持的重大修订。这些改进显著提高了 JMX 统计信息收集的性能,并提供了更多的控制。然而,它在少数特定(不常见)情况下对用户代码产生了一些影响。这些更改将在下面详细说明,并在必要时提出注意事项。

@IntegrationManagedResource

类似于 `@ManagedResource` 注解,`@IntegrationManagedResource` 将类标记为有资格导出为 MBean。但是,只有当应用程序上下文具有 `IntegrationMBeanExporter` 时,它才会被导出。

某些 Spring Integration 类(在 `org.springframework.integration` 包中)以前用 `@ManagedResource` 注解,现在同时用 `@ManagedResource` 和 `@IntegrationManagedResource` 注解。这是为了向后兼容(参见下一项)。这样的 MBean 由任何上下文 `MBeanServer` 或 `IntegrationMBeanExporter` 导出(但不能同时导出——如果两个导出器都存在,并且 bean 与 `managed-components` 模式匹配,则由集成导出器导出)。

MBean 导出器 Bean 名称模式

以前,`managed-components` 模式只包含。如果 bean 名称匹配其中一个模式,它就会被包含。现在,可以通过在其前面加上 `!` 来否定模式。例如,`!thing*, things` 匹配所有不以 `thing` 开头但包含 `things` 的 bean 名称。模式从左到右评估。第一个匹配(正向或反向)获胜,然后不再应用其他模式。

此语法添加到模式中会导致一个可能的(尽管可能不太可能)问题。如果您有一个名为 `"!thing"` 的 bean,并且在 MBean 导出器的 `managed-components` 模式中包含一个模式 `!thing`,它将不再匹配;该模式现在匹配所有不名为 `thing` 的 bean。在这种情况下,您可以在模式中用 `\` 转义 `!`。`\!thing` 模式匹配名为 `!thing` 的 bean。
IntegrationMBeanExporter 更改

`IntegrationMBeanExporter` 不再实现 `SmartLifecycle`。这意味着 `start()` 和 `stop()` 操作不再可用于注册和注销 MBean。MBean 现在在上下文初始化期间注册,并在上下文销毁时注销。

有序关闭托管操作

MBean 导出器允许 JMX 操作以有序的方式关闭应用程序。它旨在在停止 JVM 之前使用。其使用和操作在有序关闭中描述。

© . This site is unofficial and not affiliated with VMware.