控制匯流排

正如 《企業整合模式》 (EIP) 一書中所述,控制匯流排背後的理念是,用於監控和管理框架內元件的訊息系統可以與用於“應用層”訊息傳遞的系統相同。在 Spring Integration 中,我們在上述介面卡的基礎上進行構建,以便您可以透過傳送訊息來呼叫暴露的操作。

由於控制匯流排足夠強大,可以更改系統狀態,因此建議保護其訊息接收(參見 SecurityContextChannelInterceptor)並僅將控制匯流排管理(訊息源)暴露到 DMZ 區。

以下示例展示瞭如何使用 XML 配置控制匯流排

<int:control-bus input-channel="operationChannel"/>

控制匯流排有一個輸入通道,可用於呼叫應用程式上下文中的 bean 上的操作。它還具有服務啟用端點的所有常見屬性。例如,如果操作結果有返回值並且您想將其傳送到下游通道,則可以指定一個輸出通道。

控制匯流排將輸入通道上的訊息作為託管操作執行,格式為簡單的字串,例如 beanName.methodName。目標方法引數的引數必須在 IntegrationMessageHeaderAccessor.CONTROL_BUS_ARGUMENTS 頭中作為列表提供。要呼叫的 bean 和方法從 ControlBusCommandRegistry 基礎架構 bean 解析。預設情況下,ControlBusCommandRegistry 按需註冊命令:其 eagerInitialization 標誌可以透過 @EnableIntegrationManagement(loadControlBusCommands = "true") 開啟。

控制匯流排的功能類似於 JMX,因此方法符合命令資格必須滿足以下要求

  • 使用 @ManagedAttribute@ManagedOperation 註解的方法;

  • Spring 的 Lifecycle 介面(及其自 5.2 版本以來的 Pausable 擴充套件);

  • 用於配置 Spring 的幾種 TaskExecutorTaskScheduler 實現的方法。

確保您自己的方法可供控制匯流排使用的最簡單方法是使用 @ManagedAttribute@ManagedOperation 註解。由於這些註解也用於將方法暴露給 JMX MBean 登錄檔,因此它們提供了一個方便的副產品:通常,您希望暴露給控制匯流排的操作型別也適合透過 JMX 暴露)。更多資訊請參閱 ControlBusCommandRegistryControlBusMethodFilter 的 Javadoc 文件。

要在 Spring Bean 上執行方法,客戶端可以按如下方式向操作通道傳送訊息

Message<?> operation = MessageBuilder.withPayload("myServiceBean.shutdown").build();
operationChannel.send(operation);

如果要呼叫的目標方法帶有引數(例如 ThreadPoolTaskExecutor.setMaxPoolSize(int maxPoolSize)),這些值必須作為 IntegrationMessageHeaderAccessor.CONTROL_BUS_ARGUMENTS 頭提供

Message<?> operation =
        MessageBuilder.withPayload("myTaskExecutor.setMaxPoolSize")
        .setHeader(IntegrationMessageHeaderAccessor.CONTROL_BUS_ARGUMENTS, List.of(10))
        .build();
operationChannel.send(operation);

您可以將這些命令視為 JDBC 中的 PreparedStatement 例項,帶有引數繫結。引數的型別必須與方法引數的型別匹配。它們用作根據 Java 方法過載特性選擇要呼叫的方法的附加標準。例如,元件

@ManagedResource
class TestManagementComponent {

    @ManagedOperation
    public void operation() {

    }

    @ManagedOperation(description = "The overloaded operation with int argument")
    public void operation(int input) {

    }

    @ManagedOperation(description = "The overloaded operation with two arguments")
    public void operation(int input1, String input2) {

    }

    @ManagedOperation
    public int operation2() {
    	return 123;
    }

}

將暴露 3 個名為 operation 的命令。當我們呼叫 testManagementComponent.operation 命令時,我們應該為 IntegrationMessageHeaderAccessor.CONTROL_BUS_ARGUMENTS 頭選擇一個適當的值列表,以便讓 ControlBusCommandRegistry 過濾出 bean 上的目標方法。

使用 Java 註解,您可以按如下方式配置控制匯流排

@Bean
@ServiceActivator(inputChannel = "operationChannel")
public ControlBusFactoryBean controlBus() {
    return new ControlBusFactoryBean();
}

類似地,您可以按如下方式配置 Java DSL 流定義

@Bean
public IntegrationFlow controlBusFlow() {
    return IntegrationFlow.from("controlBus")
              .controlBus()
              .get();
}

如果您更喜歡使用帶有自動 DirectChannel 建立的 Lambda 表示式,可以按如下方式建立控制匯流排

@Bean
public IntegrationFlow controlBus() {
    return IntegrationFlowDefinition::controlBus;
}

在這種情況下,通道被命名為 controlBus.input

另請參閱控制匯流排 REST 控制器,瞭解如何透過 HTTP 暴露控制匯流排管理。