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 的 ` |
该适配器还可以接受对 `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 引用,指向一个对象名称模式的 `
当启用 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 提供了两个标准过滤器。`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 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 对象名称:
| 组件类型 | 对象名称 |
|---|---|
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` 属性采用下表中的值之一:
| 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 之前使用。其使用和操作在有序关闭中描述。