JMX 支持

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

您需要将此依赖项包含到您的项目中:

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

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

通知监听通道适配器

通知侦听通道适配器需要 MBean 的 JMX ObjectName,该 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 的<context:mbean-server/>元素时生成的 bean 名称相同。如果您需要使用不同的名称,请务必包含该mbean-server属性。

适配器还可以接受对 aNotificationFilter和“handback”对象的引用,以提供一些随每个通知传回的上下文。这两个属性都是可选的。扩展前面的示例以包含这些属性以及显式MBeanServerbean 名称会生成以下示例:

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

_Notification-listening 通道适配器是事件驱动的并MBeanServer直接注册到。它不需要任何轮询器配置。

仅对于此组件,object-name属性可以包含对象名称模式(例如,“org.something:type=MyType,name=*”)。在这种情况下,适配器会接收来自对象名称与模式匹配的所有 MBean 的通知。此外,该object-name属性可以包含<util:list>对对象名称模式的 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在上下文中存在。这就是为什么该<context:mbean-export/>元素也显示在前面的示例中的原因。

当消息发送到此适配器的通道时,会根据消息内容创建通知。如果有效负载是 a ,它将作为通知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-nameattribute-name是必需的。还需要 MBeanServer 引用。但是,默认情况下,它会自动检查名为 的 bean ,与前面描述mbeanServer的通知侦听通道适配器相同。以下示例显示如何使用 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 树并发送带有有效负载的消息,该有效负载是与查询匹配的对象图。默认情况下,MBean 映射到原语和简单对象,例如MapList和数组。这样做允许简单地转换为(例如)JSON。还需要 MBeanServer 引用。但是,默认情况下,它会自动检查名为 的 bean ,与前面描述mbeanServer的通知侦听通道适配器相同。以下示例显示如何使用 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配置了适当过滤器的过滤器来过滤属性。您可以使用属性提供转换器作为对 bean 定义的引用converter,也可以使用内部<bean/>定义。Spring Integration 提供了一个DefaultMBeanObjectConverter可以MBeanAttributeFilter在其构造函数参数中接受的 a。

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

操作调用通道适配器

操作调用通道适配器支持对 MBean 公开的任何托管操作进行消息驱动调用。每次调用都需要调用的操作名称和目标 MBean 的对象名称。这两个必须分别由适配器配置或 viaJmxHeaders.OBJECT_NAMEJmxHeaders.OPERATION_NAME消息头显式提供:

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

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

消息的有效负载映射到操作的参数(如果有)。带有键的Map类型化有效负载String被视为名称/值对,而一个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属性,则将回复消息发送到IntegrationMessageHeaderAccessor.REPLY_CHANNEL标头标识的通道。该标头通常由消息流的入口点自动创建,例如任何网关组件。但是,如果消息流是通过手动创建 Spring Integration 消息并将其直接发送到通道来启动的,则必须显式指定消息头或使用reply-channel属性。

MBean 导出器

配置时,Spring Integration 组件本身可能会作为 MBean 公开IntegrationMBeanExporter。要创建 的实例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 核心中提供的导出器是正交的。它注册消息通道和消息处理程序,但不注册自己。<context:mbean-export/>您可以使用标准标签公开导出器本身(以及 Spring Integration 中的某些其他组件) 。导出器附加了一些指标——例如,处理程序数量和排队消息的数量。

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

Spring Integration 4.0 引入了注解,以便在类级别使用几个有用的选项@EnableIntegrationMBeanExport来方便地配置默认integrationMbeanExporter类型的 bean 。以下示例显示了如何配置此 bean:IntegrationMBeanExporter@Configuration

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

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

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

MBean 对象名称

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

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

消息频道

`osi:type=MessageChannel,name=<channelName>`

消息源

`osi:type=MessageSource,name=<channelName>,bean=<source>`

消息处理程序

`osi:type=MessageSource,name=<channelName>,bean=<source>`

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

表 2. bean ObjectName 部分
豆值 描述

端点

封闭端点的 bean 名称(例如<service-activator>),如果有

匿名的

指示封闭端点没有用户指定的 bean 名称,因此 JMX 名称是输入通道名称。

内部的

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

处理程序/源

以上都不是。回退到toString()被监视对象的方法(处理程序或源)

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

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

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部分移至“Integration”componentType并将其设置type为“Integration”,从而可以在一个查询中选择所有 Integration MBean:`my.domain:type=Integration,*`。这样做还会在 VisualVM 等工具中将 bean 分组到域下的一个树条目下。

默认命名策略是MetadataNamingStrategy. 如果 bean 键的解析失败,导出器会将 传播default-domain到该对象以使其生成备用对象名称。如果您的自定义命名策略是 a 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 由集成导出器导出(如果 bean 匹配managed-components模式)导出)。

MBean 导出器 Bean 名称模式

Previously, the managed-components patterns were inclusive only. If a bean name matched one of the patterns, it would be included. Now, the pattern can be negated by prefixing it with !. For example, !thing*, things matches all bean names that do not start with thing except things. Patterns are evaluated left to right. The first match (positive or negative) wins, and then no further patterns are applied.

The addition of this syntax to the pattern causes one possible (although perhaps unlikely) problem. If you have a bean named "!thing" and you included a pattern of !thing in your MBean exporter’s managed-components patterns, it no longer matches; the pattern now matches all beans not named thing. In this case, you can escape the ! in the pattern with \. The \!thing pattern matches a bean named !thing.
IntegrationMBeanExporter changes

The IntegrationMBeanExporter no longer implements SmartLifecycle. This means that start() and stop() operations are no longer available to register and unregister MBeans. The MBeans are now registered during context initialization and unregistered when the context is destroyed.

Orderly Shutdown Managed Operation

MBean 导出器让 JMX 操作以有序的方式关闭应用程序。它旨在在停止 JVM 之前使用。以下示例显示了如何使用它:

public void stopActiveComponents(long howLong)

其使用和操作在有序关闭中进行了描述。


1. see XML Configuration