跳到主要内容

控制总线

QWen Plus 中英对照 Control Bus

如《企业集成模式》(EIP) 一书中所述,控制总线背后的想法是,用于监控和管理框架内组件的同一消息系统也可以用于“应用程序级别”的消息传递。在 Spring Integration 中,我们在上述适配器的基础上进行构建,以便你可以通过发送消息来调用暴露的操作。

important

由于控制总线功能强大,足以对系统状态进行更改,因此建议保护其消息接收的安全性(参见 SecurityContextChannelInterceptor),并且仅在 DMZ 中暴露控制总线管理(消息源)。

以下示例展示了如何使用 XML 配置控制总线:

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

控制总线有一个输入通道,可以访问以调用应用程序上下文中 beans 的操作。它还具有服务激活端点的所有常见属性。例如,如果操作的结果有返回值,并且您希望将该值发送到下游通道,则可以指定一个输出通道。

控制总线以简单的字符串格式(如 beanName.methodName)在输入通道上运行消息作为托管操作。目标方法参数的参数必须作为列表在 IntegrationMessageHeaderAccessor.CONTROL_BUS_ARGUMENTS 头中提供。要调用的 bean 和方法是从 ControlBusCommandRegistry 基础设施 bean 中解析的。默认情况下,ControlBusCommandRegistry 按需注册命令:可以通过 @EnableIntegrationManagement(loadControlBusCommands = "true") 将其 eagerInitialization 标志打开。

Control Bus 的功能与 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);
java

如果要调用的目标方法有参数(例如 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);
java

你可以将这些命令视为 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;
}

}
java

将暴露 3 个带有 operation 名称的命令。当我们调用 testManagementComponent.operation 命令时,我们应该为 IntegrationMessageHeaderAccessor.CONTROL_BUS_ARGUMENTS 头选择一个合适的值列表,以便让 ControlBusCommandRegistry 在 bean 上筛选出目标方法。

使用 Java 注解,你可以如下配置控制总线:

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

同样,你可以如下配置 Java DSL 流定义:

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

如果你更喜欢使用带有自动 DirectChannel 创建的 lambda,你可以如下创建一个控制总线:

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

在这种情况下,通道的名称是 controlBus.input

另请参阅 Control Bus REST Controller,用于通过 HTTP 暴露 Control Bus 管理。