開啟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,二選一:
- 在client中指定
@FeignClient(name = "service-name",
fallbackFactory = TestServiceFallback.class,
configuration = {NotBreakerConfiguration.class})
public interface TestService {
// 省略
}
- 在配置文件中指定
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