JMX Support

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

Spring Integration provides channel Adapters for receiving and publishing JMX Notifications.

你需要将此依赖项包含在你的项目中:

You need to include this dependency into your project:

  • Maven

  • Gradle

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

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

An inbound channel adapter allows for polling JMX MBean attribute values, and an outbound channel adapter allows for invoking JMX MBean operations.

Notification-listening Channel Adapter

针对通知进行侦听的通道适配器需要一个 JMX ObjectName,用于发布将该侦听器注册到的通知的 MBean。一项非常简单的配置可能如下所示:

The notification-listening channel adapter requires a JMX ObjectName for the MBean that publishes notifications to which this listener should be registered. A very simple configuration might resemble the following:

<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 属性。

The notification-listening-channel-adapter registers with an MBeanServer at startup, and the default bean name is mbeanServer, which happens to be the same bean name generated when using Spring’s <context:mbean-server/> element. If you need to use a different name, be sure to include the mbean-server attribute.

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

The adapter can also accept a reference to a NotificationFilter and a “handback” object to provide some context that is passed back with each notification. Both of those attributes are optional. Extending the preceding example to include those attributes as well as an explicit MBeanServer bean name produces the following example:

<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 注册。它不需要任何轮询程序配置。

The _Notification-listening channel adapter is event-driven and registered with the MBeanServer directly. It does not require any poller configuration.

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

For this component only, the object-name attribute can contain an object name pattern (for example, "org.something:type=MyType,name=*"). In that case, the adapter receives notifications from all MBeans with object names that match the pattern. In addition, the object-name attribute can contain a SpEL reference to a <util:list> of object name patterns, as the following example shows:

<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 的名称。

The names of the located MBean(s) are logged when DEBUG level logging is enabled.

Notification-publishing Channel Adapter

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

The notification-publishing channel adapter is relatively simple. It requires only a JMX object name in its configuration, as the following example shows:

<context:mbean-export/>

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

它还需要上下文中存在一个 MBeanExporter。这就是前面示例中也显示了 <context:mbean-export/> 元素的原因。

It also requires that an MBeanExporter be present in the context. That is why the <context:mbean-export/> element is also shown in the preceding example.

当向此适配器的通道发送消息时,通知会根据消息内容创建。如果负载是一个 String,则会将其作为通知的 message 文本传递。任何其他负载类型都会作为通知的 userData 传递。

When messages are sent to the channel for this adapter, the notification is created from the message content. If the payload is a String, it is passed as the message text for the notification. Any other payload type is passed as the userData of the notification.

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

JMX notifications also have a type, and it should be a dot-delimited String. There are two ways to provide the type. Precedence is always given to a message header value associated with the JmxHeaders.NOTIFICATION_TYPE key. Alternatively, you can provide a fallback default-notification-type attribute in the configuration, as the following example shows:

<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"/>

Attribute-polling Channel Adapter

当您需要定期检查通过 MBean 按受管理属性提供的一些值时,属性轮询通道适配器很有用。您可通过与 Spring Integration 中的任何其他轮询适配器相同的方式配置轮询器(或您可以依赖默认轮询器)。需要 object-nameattribute-name。还需要 MBeanServer 引用。但是,默认情况下,它会自动检查一个名为 mbeanServer 的 Bean,与通知侦听通道适配器 described earlier 相同。以下示例展示了如何使用 XML 配置属性轮询通道适配器:

The attribute-polling channel adapter is useful when you need to periodically check on some value that is available through an MBean as a managed attribute. You can configure the poller in the same way as any other polling adapter in Spring Integration (or you can rely on the default poller). The object-name and the attribute-name are required. An MBeanServer reference is also required. However, by default, it automatically checks for a bean named mbeanServer, same as the notification-listening channel adapter described earlier. The following example shows how to configure an attribute-polling channel adapter with 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>

Tree-polling Channel Adapter

树形轮询通道适配器查询 JMX MBean 树,并发送消息,其有效负载为与查询相匹配的对象图表。默认情况下,MBean 映射至基本类型和简单对象,如 MapList 和数组。这样做允许实现简单转换,例如 JSON。还需要 MBeanServer 引用。但是,默认情况下,它会自动检查一个名为 mbeanServer 的 Bean,与通知侦听通道适配器 described earlier 相同。以下示例展示了如何使用 XML 配置树形轮询通道适配器:

The tree-polling channel adapter queries the JMX MBean tree and sends a message with a payload that is the graph of objects that matches the query. By default, the MBeans are mapped to primitives and simple objects, such as Map, List, and arrays. Doing so permits simple transformation to (for example) JSON. An MBeanServer reference is also required. However, by default, it automatically checks for a bean named mbeanServer, same as the notification-listening channel adapter described earlier. The following example shows how to configure a tree-polling channel adapter with 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 定义的引用提供,或者可以使用内部 <bean/> 定义。Spring Integration 提供了一个 DefaultMBeanObjectConverter,它可以在构造函数参数中使用 MBeanAttributeFilter

The preceding example includes all the attributes on the selected MBeans. You can filter the attributes by providing an MBeanObjectConverter that has an appropriate filter configured. You can provide the converter as a reference to a bean definition by using the converter attribute, or you can use an inner <bean/> definition. Spring Integration provides a DefaultMBeanObjectConverter that can take a MBeanAttributeFilter in its constructor argument.

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

Spring Integration provides two standard filters. The NamedFieldsMBeanAttributeFilter lets you specify a list of attributes to include. The NotNamedFieldsMBeanAttributeFilter lets you specify a list of attributes to exclude. You can also implement your own filter.

Operation-invoking Channel Adapter

调用操作通道适配器能够对 MBean 暴露的任何受管操作进行消息驱动的调用。每个调用都需要指定要调用的操作名称和目标 MBean 的对象名称。这两个都必须通过适配器配置或分别通过 JmxHeaders.OBJECT_NAMEJmxHeaders.OPERATION_NAME 消息头显式提供:

The operation-invoking channel adapter enables message-driven invocation of any managed operation exposed by an MBean. Each invocation requires the operation name to be invoked and the object name of the target MBean. Both of these must be explicitly provided by adapter configuration or via JmxHeaders.OBJECT_NAME and JmxHeaders.OPERATION_NAME message headers, respectively:

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

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

Then the adapter only needs to be able to discover the mbeanServer bean. If a different bean name is required, then provide the mbean-server attribute with a reference.

如果存在的话,消息的负载会映射到操作的参数。键为 StringMap 类型负载会被视为名称/值对,而 List 或数组会作为简单的参数列表传递(没有显式的参数名称)。如果操作需要一个参数值,则负载可以表示那个单独的值。此外,如果操作不需要参数,则会忽略负载。

The payload of the message is mapped to the parameters of the operation, if any. A Map-typed payload with String keys is treated as name/value pairs, whereas a List or array is passed as a simple argument list (with no explicit parameter names). If the operation requires a single parameter value, the payload can represent that single value. Also, if the operation requires no parameters, the payload would be ignored.

如果你希望为单个常见操作公开一个通道,由不需要包含头的消息调用,那么最后一个选项很好用。

If you want to expose a channel for a single common operation to be invoked by messages that need not contain headers, that last option works well.

Operation-invoking Outbound Gateway

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

Similarly to the operation-invoking channel adapter, Spring Integration also provides an operation-invoking outbound gateway, which you can use when dealing with non-void operations when a return value is required. The return value is sent as the message payload to the reply-channel specified by the gateway. The following example shows how to configure an operation-invoking outbound gateway with 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 属性。

If you do not provide the reply-channel attribute, the reply message is sent to the channel identified by the IntegrationMessageHeaderAccessor.REPLY_CHANNEL header. That header is typically auto-created by the entry point into a message flow, such as any gateway component. However, if the message flow was started by manually creating a Spring Integration message and sending it directly to a channel, you must specify the message header explicitly or use the reply-channel attribute.

MBean Exporter

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

Spring Integration components may themselves be exposed as MBeans when the IntegrationMBeanExporter is configured. To create an instance of the IntegrationMBeanExporter, define a bean and provide a reference to an MBeanServer and a domain name (if desired). You can leave out the domain, in which case the default domain is org.springframework.integration. The following example shows how to declare an instance of an IntegrationMBeanExporter and an associated MBeanServer instance:

<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 中的某些其他组件)。导出器有一些度量标准附加到它上,例如,处理程序的数量和排队消息的数量。

The MBean exporter is orthogonal to the one provided in Spring core. It registers message channels and message handlers but does not register itself. You can expose the exporter itself (and certain other components in Spring Integration) by using the standard <context:mbean-export/> tag. The exporter has some metrics attached to it — for instance, a count of the number of handlers and the number of queued messages.

它还具有一些有用的操作,如 Orderly Shutdown Managed Operation 中所述。

It also has a useful operation, as discussed in Orderly Shutdown Managed Operation.

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

Spring Integration 4.0 introduced the @EnableIntegrationMBeanExport annotation to allow for convenient configuration of a default integrationMbeanExporter bean of type IntegrationMBeanExporter with several useful options at the @Configuration class level. The following example shows how to configure this bean:

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

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

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

If you need to provide more options or have several IntegrationMBeanExporter beans (such as for different MBean Servers or to avoid conflicts with the standard Spring MBeanExporter — such as through @EnableMBeanExport), you can configure an IntegrationMBeanExporter as a generic bean.

MBean Object Names

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

All the MessageChannel, MessageHandler, and MessageSource instances in the application are wrapped by the MBean exporter to provide management and monitoring features. The generated JMX object names for each component type are listed in the following table:

Table 1. MBean Object Names
Component Type Object Name

MessageChannel

  `o.s.i:type=MessageChannel,name=&lt;channelName&gt;`

MessageSource

  `o.s.i:type=MessageSource,name=&lt;channelName&gt;,bean=&lt;source&gt;`

MessageHandler

  `o.s.i:type=MessageSource,name=&lt;channelName&gt;,bean=&lt;source&gt;`

资源和处理程序的对象名称中的 bean 属性采用以下表格中的某个值:

The bean attribute in the object names for sources and handlers takes one of the values in the following table:

Table 2. bean ObjectName Part
Bean Value Description

endpoint

The bean name of the enclosing endpoint (for example <service-activator>), if there is one

anonymous

An indication that the enclosing endpoint did not have a user-specified bean name, so the JMX name is the input channel name.

internal

For well known Spring Integration default components

handler/source

None of the above. Fall back to the toString() method of the object being monitored (handler or source)

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

You can append custom elements to the object name by providing a reference to a Properties object in the object-name-static-properties attribute.

此外,自 Spring Integration 3.0 起,您可以通过设置`object-naming-strategy`属性来使用自定义 link:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jmx/export/naming/ObjectNamingStrategy.html[ObjectNamingStrategy。这样做允许更好地控制 MBean 命名,如将所有集成 MBean 分组到“Integration”类型下。以下示例展示了一个可能的自定义命名策略实现:

Also, since Spring Integration 3.0, you can use a custom ObjectNamingStrategy by setting the object-naming-strategy attribute. Doing so permits greater control over the naming of the MBeans, such as grouping all integration MBeans under an 'Integration' type. The following example shows one possible custom naming strategy implementation:

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 设置为“集成”,从而允许在一次查询中选择所有集成 MBean:my.domain:type=Integration,*。这样做还会在可视化 VM 等工具的域下将 Bean 分组到一个树条目下。

The beanKey argument is a String that contain the standard object name, beginning with the default-domain and including any additional static properties. The preceding example moves the standard type part to componentType and sets the type to 'Integration', enabling selection of all Integration MBeans in one query:`my.domain:type=Integration,*`. Doing so also groups the beans under one tree entry under the domain in such tools as VisualVM.

默认的命名策略是 MetadataNamingStrategy。导出器将 default-domain 传播到该对象,以便如果 bean 密钥的解析失败,它可以生成一个回退对象名称。如果您的自定义命名策略是 MetadataNamingStrategy(或它的子类),则导出器不会传播 default-domain。您必须在您的策略 bean 上进行配置。

The default naming strategy is a MetadataNamingStrategy. The exporter propagates the default-domain to that object to let it generate a fallback object name if parsing of the bean key fails. If your custom naming strategy is a MetadataNamingStrategy (or a subclass of it), the exporter does not propagate the default-domain. You must configure it on your strategy bean.

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

Starting with version 5.1, any bean names (represented by the name key in the object name) will be quoted if they contain any characters that are not allowed in a Java identifier (or period .).

JMX Improvements

版本 4.2 引入了一些重要改进,表示框架中的 JMX 支持进行了一次相当大的检修。这导致 JMX 统计信息收集的性能有了显着的提升,并且对其控制功能更强。但是,在一些特定的(不常见)情况下,它对于用户代码具有一定的影响。下面将详细介绍这些更改,在必要时还会予以提醒。

Version 4.2 introduced some important improvements, representing a fairly major overhaul to the JMX support in the framework. These resulted in a significant performance improvement of the JMX statistics collection and much more control thereof. However, it has some implications for user code in a few specific (uncommon) situations. These changes are detailed below, with a caution where necessary.

@IntegrationManagedResource

Similar to the @ManagedResource annotation, the @IntegrationManagedResource marks a class as being eligible to be exported as an MBean. However, it is exported only if the application context has an IntegrationMBeanExporter.

某些 Spring Integration 类(在 org.springframework.integration 包中)以前标注有 @ManagedResource,现在还同时标注了 @ManagedResource@IntegrationManagedResource。这是出于向后兼容性的考虑(请参阅下一条)。此类 MBean 由任何上下文 MBeanServerIntegrationMBeanExporter(但不是两者,如果同时出现这两个导出器,如果该 Bean 匹配 managed-components 模式,该 Bean 将由集成导出器导出)导出。

Certain Spring Integration classes (in the org.springframework.integration) package) that were previously annotated with @ManagedResource are now annotated with both @ManagedResource and @IntegrationManagedResource. This is for backwards compatibility (see the next item). Such MBeans are exported by any context MBeanServer or by an IntegrationMBeanExporter (but not both — if both exporters are present, the bean is exported by the integration exporter if the bean matches a managed-components pattern).

MBean Exporter Bean Name Patterns

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.

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

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 之前使用。以下示例展示了如何使用它:

The MBean exporter lets a JMX operation shut down the application in an orderly manner. It is intended for use before stopping the JVM. The following example shows how to use it:

public void stopActiveComponents(long howLong)

其使用和操作在 Orderly Shutdown中进行了描述。

Its use and operation are described in Orderly Shutdown.