Spring Cloud Feign+Hystrix自定義異常處理


開啟Hystrix

spring-cloud-dependencies Dalston版本之后,默認Feign對Hystrix的支持默認是關閉的,需要手動開啟。

feign.hystrix.enabled=true

開啟hystrix,可以選擇關閉熔斷或超時。
關閉熔斷:

# 全局關閉熔斷:
hystrix.command.default.circuitBreaker.enabled: false
# 局部關閉熔斷:
hystrix.command.<HystrixCommandKey>.circuitBreaker.enabled: false

設置超時:

# 全局設置超時:
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 1000
# 局部設置超時:
hystrix.command.<HystrixCommandKey>.execution.isolation.thread.timeoutInMilliseconds: 1000

關閉超時:

# 全局關閉:
hystrix.command.default.execution.timeout.enabled: false
# 局部關閉:
hystrix.command.<HystrixCommandKey>.execution.timeout.enabled: false

Fallback

fallback 是 Hystrix 命令執行失敗時使用的后備方法,用來實現服務的降級處理邏輯。在 HystrixCommand 中可以通過重載 getFallback() 方法來實現服務降級邏輯,Hystrix 會在 run() 執行過程中出現錯誤、超時、線程池拒絕、短路熔斷等情況時,執行 getFallback() 方法內的邏輯。

通常,當 HystrixCommand 的主方法(run()) 中拋出異常時,便會觸發 getFallback()。除了一個例外 —— HystrixBadRequestException。當拋出 HystrixBadRequestException,不論當前 Command 是否定義了 getFallback(),都不會觸發,而是向上拋出異常。

如果實現業務時有一些異常希望能夠向上拋出,而不是觸發 Fallback 策略,便可以封裝到 HystrixBadRequestException 中。

getFallback() 的執行時間並不受 HystrixCommand 的超時時間的控制。

Feign對異常的封裝

通過實現FallbackFactory,可以在create方法中獲取到服務拋出的異常。但是請注意,這里的異常是被Feign封裝過的異常,不能直接在異常信息中看出原始方法拋出的異常。

1.自定義error decoder,不進入熔斷,保留原始報錯信息,向上層拋出的方法。

package test.config;

import com.alibaba.fastjson.JSONObject;
import com.netflix.hystrix.exception.HystrixBadRequestException;
import feign.Response;
import feign.Util;
import feign.codec.ErrorDecoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;

public class NotBreakerConfiguration {
    @Bean
    public ErrorDecoder errorDecoder() {
        return new SpecialErrorDecoder();
    }
    /**
     * 自定義錯誤
     */
    public class SpecialErrorDecoder implements ErrorDecoder {
        private Logger logger = LoggerFactory.getLogger(getClass());
        @Override
        public Exception decode(String methodKey, Response response) {
            Exception exception = null;
            try {
                String json = Util.toString(response.body().asReader());
                exception = new RuntimeException(json);
                JsonResult result = JSONObject.parseObject(json, JsonResult.class);
                // 業務異常包裝成 HystrixBadRequestException,不進入熔斷邏輯
                if (!result.isSuccess()) {
                    exception = new HystrixBadRequestException(result.getMessage());
                }
            } catch (IOException ex) {
                logger.error(ex.getMessage(), ex);
            }
            return exception;
        }
    }
}

2.為FeignClient指定error decoder,二選一:

  1. 在client中指定
@FeignClient(name = "service-name", 
fallbackFactory = TestServiceFallback.class, 
configuration = {NotBreakerConfiguration.class})
public interface TestService {
    // 省略
}
  1. 在配置文件中指定
feign:
  client:
    config:
      servive-name:
        error-decoder: NotBreakerConfiguration

3.上層調用

package test;

import com.netflix.hystrix.exception.HystrixBadRequestException;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class TestServiceApi {

    public void withdraw() {
        try {
            // 省略feign client方法調用
        } catch (HystrixBadRequestException e) {
            // 原始錯誤信息
            log.info(e.getMessage());
        } catch (Exception e) {
            log.error("error", e);
        }
    }
}

參考:
https://blog.csdn.net/lvyuan1234/article/details/77155919
https://juejin.im/post/5bae37ca5188255c652d4c6a
https://my.oschina.net/xiaominmin/blog/2986631/print


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM