在Spring Cloud 使用feign 的時候,須要明確指定fallback 策略,否則會提示錯誤。
先來看默認的feign service 是要求怎麼作的。feign service 定義一個 factory 和 fallback 的類git
@FeignClient(value = ServiceNameConstants.UMPS_SERVICE, fallbackFactory = RemoteLogServiceFallbackFactory.class) public interface RemoteLogService {}
可是咱們大多數狀況的feign 降級策略爲了保證冪等都會很簡單,輸出錯誤日誌便可。
相似以下代碼,在企業中開發很是不方便github
@Slf4j @Component public class RemoteLogServiceFallbackImpl implements RemoteLogService { @Setter private Throwable cause; @Override public R<Boolean> saveLog(SysLog sysLog, String from) { log.error("feign 插入日誌失敗", cause); return null; } }
@FeignClient(value = ServiceNameConstants.UMPS_SERVICE) public interface RemoteLogService {}
@Configuration @ConditionalOnClass({HystrixCommand.class, HystrixFeign.class}) protected static class HystrixFeignConfiguration { @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @ConditionalOnProperty("feign.hystrix.enabled") public Feign.Builder feignHystrixBuilder(FeignContext feignContext) { return PigxHystrixFeign.builder(feignContext) .decode404() .errorDecoder(new PigxFeignErrorDecoder()); } }
@Override public <T> T target(Target<T> target) { Class<T> targetType = target.type(); FeignClient feignClient = AnnotatedElementUtils.getMergedAnnotation(targetType, FeignClient.class); String factoryName = feignClient.name(); SetterFactory setterFactoryBean = this.getOptional(factoryName, feignContext, SetterFactory.class); if (setterFactoryBean != null) { this.setterFactory(setterFactoryBean); } // 如下爲獲取降級策略代碼,構建降級,這裏去掉了降級非空的非空的校驗 Class<?> fallback = feignClient.fallback(); if (fallback != void.class) { return targetWithFallback(factoryName, feignContext, target, this, fallback); } Class<?> fallbackFactory = feignClient.fallbackFactory(); if (fallbackFactory != void.class) { return targetWithFallbackFactory(factoryName, feignContext, target, this, fallbackFactory); } return build().newInstance(target); }
Feign build(@Nullable final FallbackFactory<?> nullableFallbackFactory) { super.invocationHandlerFactory((target, dispatch) -> new PigxHystrixInvocationHandler(target, dispatch, setterFactory, nullableFallbackFactory)); super.contract(new HystrixDelegatingContract(contract)); return super.build(); }
@Override @Nullable @SuppressWarnings("unchecked") protected Object getFallback() { // 若是 @FeignClient 沒有配置降級策略,使用動態代理建立一個 if (fallbackFactory == null) { fallback = PigxFeignFallbackFactory.INSTANCE.create(target.type(), getExecutionException()); } else { // 若是 @FeignClient配置降級策略,使用配置的 fallback = fallbackFactory.create(getExecutionException()); } }
public T create(final Class<?> type, final Throwable cause) { return (T) FALLBACK_MAP.computeIfAbsent(type, key -> { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(key); enhancer.setCallback(new PigxFeignFallbackMethod(type, cause)); return enhancer.create(); }); }
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) { log.error("Fallback class:[{}] method:[{}] message:[{}]", type.getName(), method.getName(), cause.getMessage()); if (R.class == method.getReturnType()) { final R result = cause instanceof PigxFeignException ? ((PigxFeignException) cause).getResult() : R.builder() .code(CommonConstants.FAIL) .msg(cause.getMessage()).build(); return result; } return null; }