HystrixCommand 的奇怪行为

Posted

技术标签:

【中文标题】HystrixCommand 的奇怪行为【英文标题】:strange behavior of HystrixCommand 【发布时间】:2021-02-01 05:41:10 【问题描述】:

项目使用SpringBoot(2.3.4)SpringCloud(Hoxton.SR8)。 共有三个类:BillController、BillService(interface)和BillServiceImpl(实现BillService),BillController调用BillService中声明的函数getBillList

在BillServiceImpl中,有两种方法,一种是getBillList,另一种是simulateUnstableServicegetBillList调用simulateUnstableService,而在simulateUnstableService中只是一个long sleep(2000)。

奇怪的是,如果我用HystrixCommand 注释getBillList,那么它会按我的预期工作。但是,如果我将HystrixCommand 移动到注释simulateUnstableService,则没有中断,这意味着超时不会触发Circuit Breaker

@Service
public class BillServiceImpl implements BillService 

    @Override
    // have effact
    @HystrixCommand(
            commandProperties = 
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
            
    )
    public List<Bill> getBillList(long userId) 
        return simulateUnstableService(userId);
    

// no effact
//    @HystrixCommand(
//            commandProperties = 
//                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
//            
//    )
    public List<Bill> simulateUnstableService(long userId) 
        try 
            Thread.sleep(2000);
         catch (InterruptedException e) 
            e.printStackTrace();
        

        return new ArrayList<>();
    

此外,如果我只是将 simulateUnstableService 方法内容复制到 getBillList,并使用 HystrixCommand 对 getBillList 进行注释,那么断路器也可以工作。 为什么?

【问题讨论】:

@HystrixCommand 创建了一个代理,因此,在同一个类中调用一个方法没有对代理的引用,也没有 hystrix 功能。您需要分开调用或使用 api 而不是注释 【参考方案1】:

当电路中断时,会调用回退方法。我们需要在 hystrix 命令中提及 fallback 方法。 fallback 方法与被 hystrix 注解的方法具有相同的签名。

simulateUnstableService 是您的后备方法吗?

@HystrixCommand(fallbackMethod='yourFallbackMethod'
            commandProperties = 
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
            
    )
    public List<Bill> getBillList(long userId) 
        return simulateUnstableService(userId);
    

此外,最好在 application.properties 文件中添加 hystrix 命令属性,而不是与注释一起提供。

【讨论】:

【参考方案2】:

很好的问题。

Hystrix 使用 AOP 来包装被调用的方法并提供电路制动功能。实际上有一个切面类HystrixCommandAspect.java 定义了用于实现此目的的环绕建议。

现在,如果您从类中调用方法,AOP 将无法正常工作。请参阅此答案以获得更清晰的信息-Spring AOP not working for method call inside another method

【讨论】:

以上是关于HystrixCommand 的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

Spring cloud Hystrix的配置属性优先级和详解

CSV(Comma-Separate-Values)逗号分隔值文件

hystrix文档翻译之插件

HystrixCommand实战

在@HystrixCommand 回退方法中获取失败异常

这个异步 HystrixCommand 有啥问题?