# JMX 支持
# JMX 支持
Spring 集成提供了用于接收和发布 JMX 通知的通道适配器。
你需要在项目中包含此依赖项:
Maven
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jmx</artifactId>
<version>5.5.9</version>
</dependency>
Gradle
compile "org.springframework.integration:spring-integration-jmx:5.5.9"
入站通道适配器允许轮询 JMX MBean 属性值,出站通道适配器允许调用 JMX MBean 操作。
# 通知-监听通道适配器
通知监听通道适配器需要一个 JMX,用于发布此侦听器应注册到的通知的 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 属性。 |
---|
适配器还可以接受对NotificationFilter
和“handback”对象的引用,以提供与每个通知一起回传的某些上下文。这两个属性都是可选的。将前面的示例扩展到包括这些属性以及显式的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
注册。它不需要任何 Poller 配置。
仅对于这个组件,object-name 属性可以包含一个对象名模式(例如,“org.something:type=mytype,name=*”)。,在这种情况下,适配器接收来自所有具有匹配该模式的对象名的 MBean 的通知。,此外, , object-name 属性可以包含对<util:list> 对象名称模式的 SPEL 引用,如下例所示:<br/><jmx:notification-listening-channel-adapter id="manyNotificationsAdapter"<br/> channel="manyNotificationsChannel"<br/> object-name="#{patterns}"/><br/><br/><util:list id="patterns"><br/> <value>org.foo:type=Foo,name=*</value><br/> <value>org.foo:type=Bar,name=*</value><br/></util:list><br/> 启用调试级别日志时,将记录定位的 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/>
元素也显示在前面的示例中的原因。
当消息被发送到此适配器的通道时,将根据消息内容创建通知。如果有效负载是String
,则作为通知的message
文本传递。任何其他有效负载类型都将作为通知的userData
传递。
JMX 通知还具有type
,并且应该是以点分隔的String
。有两种方法可以提供type
。始终优先考虑与JmxHeaders.NOTIFICATION_TYPE
键关联的消息标头值。或者,你可以在配置中提供一个 fallbackdefault-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 集成中的任何其他轮询适配器相同的方式配置 Poller(或者可以依赖默认的 Poller)。需要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 树,并发送一条带有有效负载的消息,该负载是与查询匹配的对象的图形。默认情况下,MBean 映射到原语和简单对象,例如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 定义的引用,或者可以使用内部<bean/>
定义。 Spring 集成提供了一个DefaultMBeanObjectConverter
,它可以在其构造函数参数中接受一个MBeanAttributeFilter
。
Spring 集成提供了两个标准过滤器。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 与操作调用通道适配器类似,集成还提供了一个操作调用出站网关,当需要返回值时,可以在处理非 void 操作时使用该网关。返回值作为消息有效负载发送到网关指定的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 集成消息并将其直接发送到通道来启动的,则必须显式地指定消息头,或者使用reply-channel
属性。
# MBean 出口商
Spring 当IntegrationMBeanExporter
被配置时,集成组件本身可以作为 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 Core 中提供的输出器是正交的。 它注册消息通道和消息处理程序,但不注册本身。 通过使用标准 <context:mbean-export/> 标记,可以公开导出程序本身(以及 Spring 集成中的某些其他组件),导出程序附带了一些度量指标,例如,计算处理程序的数量和排队消息的数量。 它还具有一个有用的操作,如有序停机管理运行中所讨论的。 |
---|
Spring Integration4.0 引入了@EnableIntegrationMBeanExport
注释,以允许方便地配置类型integrationMbeanExporter
Bean 的默认IntegrationMBeanExporter
的@Configuration
类级别的几个有用选项。下面的示例展示了如何配置这个 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。
# MBean 对象名
应用程序中的所有MessageChannel
、MessageHandler
和MessageSource
实例都由 MBean Exporter 包装,以提供管理和监视功能。下表列出了为每个组件类型生成的 JMX 对象名:
Component Type | 对象名称 |
---|---|
MessageChannel | <br/> `o.s.i:type=MessageChannel,name=<channelName>`<br/> |
MessageSource | <br/> `o.s.i:type=MessageSource,name=<channelName>,bean=<source>`<br/> |
MessageHandler | <br/> `o.s.i:type=MessageSource,name=<channelName>,bean=<source>`<br/> |
源和处理程序的对象名中的bean
属性接受下表中的一个值:
Bean Value | 说明 |
---|---|
endpoint | Bean 封闭端点的名称(例如<service-activator> ),如果有一个 |
anonymous | Bean 表示封闭端点没有用户指定的名称,因此 JMX 名称是输入通道名称。 |
internal | 对于众所周知的 Spring 集成缺省组件 |
handler/source | 以上都不是。 返回被监视对象的 toString() 方法(处理程序或源) |
可以通过在object-name-static-properties
属性中提供对Properties
对象的引用,将自定义元素追加到对象名。
此外,由于 Spring Integration3.0,你可以通过设置ObjectNamingStrategy
属性来使用自定义[ObjectNamingStrategy
](https://DOCS. Spring.io/ Spring/DOCS/current/javadoc-api/org/springframework/jmx/export/naming/objectnamingstrategy.html)。这样做可以对 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
部分移动到componentType
,并将type
设置为“集成”,从而能够在一个查询中选择所有集成 MBean:my.domain:type=Integration,\*
。这样做还可以在 VisualVM 等工具中将 bean 分组到域下的一个树条目下。
默认的命名策略是[MetadataNamingStrategy ](https://DOCS. Spring.io/ Spring/DOCS/current/javadoc-api/org/springframework/jmx/export/naming/metadatanamingstrategy.html)。导出人员将 default-domain 传播到该对象,以便在解析 Bean 键失败时让它生成一个后备对象名,如果你的自定义命名策略是 MetadataNamingStrategy (或它的一个子类),导出程序不传播default-domain 。你必须在策略 Bean 上对其进行配置。 |
---|
从版本 5.1 开始;任何 Bean 名称(由对象名称中的name
键表示),如果它们包含 Java 标识符(或句号.
)中不允许的任何字符,都将被引用。
# JMX 改进
版本 4.2 引入了一些重要的改进,代表了对框架中的 JMX 支持的一次相当大的改革。这些结果导致了 JMX 统计数据收集的性能的显著改善,并对其进行了更多的控制。然而,在一些特定的(不常见的)情况下,它对用户代码有一些影响。下文详细介绍了这些变化,必要时请谨慎从事。
@IntegrationManagedResource
与@ManagedResource
注释类似,@IntegrationManagedResource
将一个类标记为有资格作为 MBean 导出。但是,只有当应用程序上下文具有IntegrationMBeanExporter
时,才会导出它。
Spring 某些集成类(在org.springframework.integration
)包中)以前用@ManagedResource
注释,现在用@ManagedResource
和@IntegrationManagedResource
注释。这是为了向后兼容(参见下一项)。这样的 MBean 通过任何上下文MBeanServer
或IntegrationMBeanExporter
导出(但不是两者都导出——如果两个出口商都存在,则如果 Bean 匹配managed-components
模式,则 Bean 由集成出口商导出)。
MBean Exporter Bean 名称模式
以前,managed-components
模式仅包含。如果 Bean 名称与其中一种模式相匹配,则该名称将被包括在内。现在,可以通过在模式前加上!
来否定该模式。例如,!thing*, things
匹配所有不以thing
开头的 Bean 名称,但things
除外。模式是从左到右计算的。第一场比赛(正面或负面)获胜,然后不再应用其他模式。
将此语法添加到模式中会导致一个可能的(尽管可能不太可能)问题, 如果你的 Bean 名为 "!thing" ,并且你在 MBean Exporter 的managed-components 模式中包含了!thing 的模式,它不再匹配;模式现在匹配所有未命名thing 的 bean。在这种情况下,你可以使用 \ 在模式中转义! 。\!thing 模式匹配名为!thing 的 Bean 的 Bean 模式。 |
---|
整合-------------------------------------------------------
IntegrationMBeanExporter
不再实现SmartLifecycle
。这意味着start()
和stop()
操作不再可用于注册和取消注册 MBean。MBean 现在在上下文初始化期间注册,在上下文被销毁时取消注册。
# 有序关停托管运行
MBean Exporter 允许一个 JMX 操作以有序的方式关闭应用程序。它是在停止 JVM 之前使用的。下面的示例展示了如何使用它:
public void stopActiveComponents(long howLong)
其用途和操作在有序关机中进行了说明。