如何说 Hystrix 不会为 Hystrix 命令中的某些异常触发回退

Posted

技术标签:

【中文标题】如何说 Hystrix 不会为 Hystrix 命令中的某些异常触发回退【英文标题】:How to say Hystrix not to trigger fallback for some of the exceptions in Hystrix command 【发布时间】:2017-10-30 00:47:45 【问题描述】:

我们通过直接扩展 HystrixCommand 类来使用 Hystrix 功能。但是对于一些业务异常,正在触发Hystrix的fallback方法。

我不想针对某些业务特定异常触发 Hystrix 回退。我如何在没有基于注释的情况下实现它?

【问题讨论】:

【参考方案1】:

使用 ignoreExceptions 注释参数

@HystrixCommand(ignoreExceptions =  BaseException.class, MissingServletRequestParameterException.class, TypeMismatchException.class )

见https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica#error-propagation

我看到您正在扩展 HystrixCommand 而不是使用注释,但这没关系,只需在命令中设置该属性,它应该具有相同的效果。

不幸的是,Hystrix 命令是由 Builder 模式创建的,因此您必须进行一些黑客操作。在 HystrixCommandBuilder 中使用的 DefaultProperties.java 中添加了 ignoreExceptions

【讨论】:

据我了解。在 HystrixCommandBuilder 的 ignoreexceptions 方法中,他只是在复制异常列表。但是根据方法注释,我了解到这些被忽略的异常可以包含在 Hystrixbadrequestexception 中。但是你能告诉我如何做到这一点,并以更好的方式使用代码 sn-p “只需在命令中设置该属性”-HystrixCommand 中没有此类属性【参考方案2】:

如果您将逻辑包装在 try/catch 中并在 HystrixBadRequestException 中重新抛出任何异常,则它不会触发回退。

@Override
protected Object run() throws Exception 
    try 
        return //call goes here
    
    catch (Throwable e) 
        //We wrap any exceptions in a HystrixBadRequestException because this way any other errors will not
        //trip the short circuit
        throw new HystrixBadRequestException("Exception thrown hystrix call", e);
    

来自文档: http://netflix.github.io/Hystrix/javadoc/com/netflix/hystrix/exception/HystrixBadRequestException.html

表示带有提供的参数或状态的错误而不是执行失败的异常。 与 HystrixCommand 抛出的所有其他异常不同,这不会触发回退,不计入故障指标,因此不会触发断路器。

注意:这仅应在错误是由于用户输入(例如 IllegalArgumentException)引起时使用,否则它会破坏容错和回退行为的目的。

【讨论】:

【参考方案3】:

有两种方法可以做到这一点。

    使用 HystrixCommand 注解并指定异常类型。

    @HystrixCommand(ignoreExceptions =  HttpStatusCodeException.class, JsonMappingException.class )
    

    使用“HystrixBadRequestException”并自定义代码以忽略少数异常情况或状态代码。此实现将检查您的后端 API 合同预期的异常的特定错误代码,并且不会调用 hystrix 回退。抛出“HystrixBadRequestException”不会算作 hystrix 故障。

    @HystrixCommand(commandKey = "MyHystrixCommand", fallbackMethod = "myHystrixFallback", threadPoolKey = "ThreadPoolKey")
    public ResponseEntity<String> getServiceCallResponse(String serviceUrl, HttpEntity<?> entity) 
    ResponseEntity<String> resp = null;
    try 
    resp = restTemplate.exchange(serviceUrl, HttpMethod.POST, entity, String.class)
            .getBody();
    
    catch(Exception e) 
        handleExceptionForHystrix("getServiceCallResponse", e);
    
    return resp;
    
    
    private void handleExceptionForHystrix(String function, Exception e) 
            if (e instanceof HttpStatusCodeException) 
                HttpStatus httpStatusCode = ((HttpStatusCodeException)e).getStatusCode();
                if(httpStatusCode.equals(HttpStatus.BAD_REQUEST) || httpStatusCode.equals(HttpStatus.INTERNAL_SERVER_ERROR)) 
                    throw new HystrixBadRequestException("Hystrix Bad Request Exception Occurred" + httpStatusCode, e);
                
                throw new RuntimeException(function, e);
            
            throw new RuntimeException(function, e);
        
    
    
    public ResponseEntity<String> myHystrixFallback(String serviceUrl, HttpEntity<?> entity, Throwable hystrixCommandExp) 
            return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
        
    

【讨论】:

以上是关于如何说 Hystrix 不会为 Hystrix 命令中的某些异常触发回退的主要内容,如果未能解决你的问题,请参考以下文章

Hystrix入门指南

Hystrix入门指南

Spring Cloud Hystrix基本原理

12Feign整合断路器Hystrix

回退禁用 - Hystrix

Hystrix-Dashboard仪表盘