RequestHandlerCircuitBreakerAdvice下游Service Activator故障时失效问题咨询
RequestHandlerCircuitBreakerAdvice 使用疑问解答
问题场景
在Spring Integration中使用RequestHandlerCircuitBreakerAdvice时遇到如下问题:
- 将该通知添加到
passThru和passThruSecond这两个ServiceActivator上时,下游的JmsOutboundGateway(firstHandler或secondHandler)出现故障,断路器无法触发。 - 但直接将
RequestHandlerCircuitBreakerAdvice添加到JmsOutboundGateway的adviceChain中(如下代码),并移除带断路器的上游ServiceActivator后,断路器能正常工作:
gateway.setAdviceChain(Collections.singletonList(requestHandlerCircuitBreakerAdvice));
疑问:这是否属于正常行为?即断路器仅在同一ServiceActivator直接发生故障时才生效?还是说在使用Direct Channel(同一线程)的情况下,下游ServiceActivator发生故障时也应生效?
无法触发断路器的代码示例
MessagingGateway定义
@MessagingGateway(name = "LocalGateway") public interface LocalGateway { @Gateway(requestChannel = "inputLocalChannel") ListenableFuture<Message<String>> sendMsg(Message<String> request); }
配置类代码
@Bean public RequestHandlerCircuitBreakerAdvice requestHandlerCircuitBreakerAdvice(){ RequestHandlerCircuitBreakerAdvice requestHandlerCircuitBreakerAdvice = new RequestHandlerCircuitBreakerAdvice(); requestHandlerCircuitBreakerAdvice.setThreshold(2); requestHandlerCircuitBreakerAdvice.setHalfOpenAfter(20000); return requestHandlerCircuitBreakerAdvice; } @Bean MessageChannel inputLocalGatewayChannel(){ DirectChannel channel = new DirectChannel(); return channel; } @Bean MessageChannel inputLocalSecondGatewayChannel(){ DirectChannel channel = new DirectChannel(); return channel; } @ServiceActivator(inputChannel = "inputLocalChannel", outputChannel = "inputLocalGatewayChannel", adviceChain = "requestHandlerCircuitBreakerAdvice") public Message passThru(Message message){ return message; } @ServiceActivator(inputChannel = "inputLocalChannel", outputChannel = "inputLocalSecondGatewayChannel", adviceChain = "requestHandlerCircuitBreakerAdvice") public Message passThruSecond(Message message){ return message; } @Bean @ServiceActivator(inputChannel = "inputLocalGatewayChannel") public JmsOutboundGateway firstHandler(){ // some code } @Bean @ServiceActivator(inputChannel = "inputLocalSecondGatewayChannel") public JmsOutboundGateway secondHandler(){ // some code }
解答
这属于正常行为,核心原因在于RequestHandlerCircuitBreakerAdvice的作用范围设计:
- 它是绑定到单个
MessageHandler实例的通知,仅会捕获该handler执行handleRequestMessage方法时抛出的异常。 - 当你把Advice加在
passThru这类ServiceActivator上时,该handler的逻辑只是简单返回消息并发送到输出通道,本身不会抛出任何异常——下游JmsOutboundGateway的故障异常,是在下游handler的handleRequestMessage方法执行时抛出的,这个异常不会回传到上游passThru的handler调用链中(因为passThru的任务已经完成,它不负责下游的执行结果)。 - 即便是使用DirectChannel(同步线程执行),上游handler的Advice也无法捕获下游handler的异常,因为两者是独立的MessageHandler实例,Advice的作用范围严格局限于自身绑定的handler。
正确的用法是将RequestHandlerCircuitBreakerAdvice直接绑定到可能抛出异常的目标handler上(比如你的JmsOutboundGateway),这样才能在该handler故障时正确触发断路器的熔断逻辑。
内容的提问来源于stack exchange,提问作者Luke
相关产品推荐
相关产品推荐

