JMX 支援

Spring Integration 提供通道適配器,用於接收和發布 JMX 通知。

您需要將此依賴項包含到您的專案中

  • Maven

  • Gradle

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

入站通道適配器允許輪詢 JMX MBean 屬性值,而出站通道適配器允許調用 JMX 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 屬性。

適配器還可以接受對 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 引用,如下列範例所示

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

它還要求 context 中存在 MBeanExporter。這就是為什麼前面的範例中也顯示了 <context:mbean-export/> 元素。

當訊息傳送到此適配器的通道時,會從訊息內容建立通知。如果 payload 是 String,則它會作為通知的 message 文字傳遞。任何其他 payload 類型都會作為通知的 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 中設定任何其他輪詢適配器一樣設定 poller(或者您可以依賴預設 poller)。object-nameattribute-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 樹,並傳送訊息,其 payload 是與查詢匹配的物件圖。預設情況下,MBean 會映射到原始類型和簡單物件,例如 MapList 和陣列。這樣做允許簡單轉換為(例如)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 Integration 提供了一個 DefaultMBeanObjectConverter,它可以在其建構子引數中採用 MBeanAttributeFilter

Spring Integration 提供了兩個標準篩選器。NamedFieldsMBeanAttributeFilter 允許您指定要包含的屬性列表。NotNamedFieldsMBeanAttributeFilter 允許您指定要排除的屬性列表。您也可以實作自己的篩選器。

操作調用通道適配器

操作調用通道適配器啟用訊息驅動的調用,用於調用 MBean 公開的任何受管理操作。每次調用都需要要調用的操作名稱和目標 MBean 的物件名稱。這兩者都必須透過適配器設定或透過 JmxHeaders.OBJECT_NAMEJmxHeaders.OPERATION_NAME 訊息標頭顯式提供

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

然後,適配器只需要能夠發現 mbeanServer bean。如果需要不同的 bean 名稱,則提供帶有引用的 mbean-server 屬性。

訊息的 payload 會映射到操作的參數(如果有的話)。具有 String 鍵的 Map 類型 payload 被視為名稱/值對,而 List 或陣列則作為簡單的引數列表傳遞(沒有顯式的參數名稱)。如果操作需要單個參數值,則 payload 可以表示該單個值。此外,如果操作不需要任何參數,則會忽略 payload。

如果您想要公開一個通道,用於訊息調用要調用的單個通用操作,而不需要包含標頭,則最後一個選項非常適合。

操作調用出站閘道

與操作調用通道適配器類似,Spring Integration 還提供了操作調用出站閘道,當處理需要傳回值的非 void 操作時,可以使用它。傳回值作為訊息 payload 傳送到閘道指定的 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 Exporter

當設定 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 exporter 與 Spring core 中提供的 exporter 是正交的。它註冊訊息通道和訊息處理器,但不註冊自身。您可以使用標準 <context:mbean-export/> 標籤公開 exporter 本身(以及 Spring Integration 中的某些其他元件)。exporter 附加了一些指標,例如處理器數量和排隊訊息數量。

它還具有一個有用的操作,如 有序關閉受管理操作 中所述。

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 物件名稱

應用程式中的所有 MessageChannelMessageHandlerMessageSource 實例都由 MBean exporter 包裝,以提供管理和監控功能。下表列出了每種元件類型產生的 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 ObjectName 部分
Bean 值 描述

endpoint

封閉端點的 bean 名稱(例如 <service-activator>),如果有的話

anonymous

指示封閉端點沒有使用者指定的 bean 名稱,因此 JMX 名稱是輸入通道名稱。

internal

適用於眾所周知的 Spring Integration 預設元件

handler/source

以上皆非。回退到正在監控的物件(處理器或來源)的 toString() 方法

您可以透過在 object-name-static-properties 屬性中提供對 Properties 物件的引用,將自訂元素附加到物件名稱。

此外,自 Spring Integration 3.0 以來,您可以使用自訂 ObjectNamingStrategy,方法是設定 object-naming-strategy 屬性。這樣做可以更好地控制 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',從而在一個查詢中啟用選擇所有 Integration MBean:`my.domain:type=Integration,*`。這樣做還可以在 VisualVM 等工具中將 bean 分組在網域下的單個樹狀結構條目下。

預設命名策略是 MetadataNamingStrategy。exporter 將 default-domain 傳播到該物件,以便在解析 bean 鍵失敗時產生後備物件名稱。如果您的自訂命名策略是 MetadataNamingStrategy(或其子類別),則 exporter 不會傳播 default-domain。您必須在您的策略 bean 上設定它。

從版本 5.1 開始,如果任何 bean 名稱(由物件名稱中的 name 鍵表示)包含 Java 識別碼(或句點 .)中不允許的任何字元,則會將其引號括起來。

JMX 改善

版本 4.2 引入了一些重要的改進,代表了框架中 JMX 支援的相當大的改進。這些改進顯著提高了 JMX 統計資訊收集的效能,並對其進行了更多控制。但是,在一些特定(不常見)的情況下,它對使用者程式碼有一些影響。以下詳細介紹了這些變更,並在必要時發出警告。

@IntegrationManagedResource

@ManagedResource 註解類似,@IntegrationManagedResource 將類別標記為符合條件以作為 MBean 匯出。但是,僅當應用程式 context 具有 IntegrationMBeanExporter 時才會匯出它。

某些先前使用 @ManagedResource 註解的 Spring Integration 類別(在 org.springframework.integration 套件中)現在同時使用 @ManagedResource@IntegrationManagedResource 進行註解。這是為了向後兼容性(請參閱下一個項目)。這些 MBean 由任何 context MBeanServerIntegrationMBeanExporter 匯出(但不是兩者都匯出 - 如果兩個 exporter 都存在,則如果 bean 與 managed-components 模式匹配,則該 bean 由整合 exporter 匯出)。

MBean Exporter Bean 名稱模式

先前,managed-components 模式僅包含。如果 bean 名稱與其中一個模式匹配,則會包含它。現在,可以透過在模式前面加上 ! 來否定模式。例如,!thing*, things 匹配除了 things 之外的所有不以 thing 開頭的 bean 名稱。模式從左到右評估。第一個匹配項(正面或負面)獲勝,然後不再應用其他模式。

將此語法新增到模式會導致一個可能的問題(儘管可能不太可能)。如果您有一個名為 "!thing" 的 bean,並且您在 MBean exporter 的 managed-components 模式中包含 !thing 模式,則它不再匹配;該模式現在匹配所有未命名為 thing 的 bean。在這種情況下,您可以使用 \ 逸出模式中的 !\!thing 模式匹配名為 !thing 的 bean。
IntegrationMBeanExporter 變更

IntegrationMBeanExporter 不再實作 SmartLifecycle。這表示 start()stop() 操作不再可用於註冊和取消註冊 MBean。MBean 現在在 context 初始化期間註冊,並在 context 銷毀時取消註冊。

有序關閉受管理操作

MBean exporter 允許 JMX 操作以有序方式關閉應用程式。它旨在在停止 JVM 之前使用。下列範例顯示如何使用它

public void stopActiveComponents(long howLong)

其使用和操作在 有序關閉 中描述。