如果使用 Feign.Builder 手动创建 Feign Client,则不调用 Hystrix 回退方法

Posted

技术标签:

【中文标题】如果使用 Feign.Builder 手动创建 Feign Client,则不调用 Hystrix 回退方法【英文标题】:Hystrix fallback method not called if Feign Client manually created with Feign.Builder 【发布时间】:2019-11-05 06:29:53 【问题描述】:

我正在尝试创建一个 Feign 客户端,该客户端在失败时具有回退方法。

通过以下示例,我创建了一个简单的 Feign 客户端:

@Component
@FeignClient(value = "authenticationClient", fallback = AuthenticationClientFallback.class)
public interface AuthenticationClient

@RequestMapping(method = RequestMethod.GET, value = "/auth/userinfo")
UserInfoResource getUserInfo(@RequestHeader("Authorization") String token);

@RequestMapping(method = RequestMethod.GET, value = "/auth/token")
TokenResource getToken(@RequestHeader("Authorization") String basicAuth);

AuthenticaionClientFallback 类如下:

 @Component
    public class AuthenticationClientFallback implements AuthenticationClient
    
        public static final String NO_TOKEN = "No Token";

        @Override
        public UserInfoResource getUserInfo(String token)
        
            return null;
        

        @Override
        public TokenResource getToken(String basicAuth)
        
            return new TokenResource(NO_TOKEN);
         

当我使用带有@Autowire 注释的客户端时,会触发回退。但我需要创建自己的 feign 客户端实例,以便动态设置 URL。

AuthenticationClient的初始化:

public AuthenticationClient getAuthenticationClient()
    
        return HystrixFeign.builder().contract(new SpringMvcContract())
                 .encoder(new JacksonEncoder())
                 .decoder(new JacksonDecoder())
                 .client(new OkHttpClient())
                 .logger(new Slf4jLogger(AuthenticationClient.class))
                 .logLevel(Logger.Level.FULL).target(AuthenticationClient.class, getTargetURL());
    

现在我的后备方法永远不会被调用,只是抛出一个 FeignException 并返回一个 401 状态代码的消息。

PS 我在 .yml 文件中设置了feign.hystrix.enabled=true,并在应用程序级别设置了@EnableCircuitBreaker。

【问题讨论】:

如果您使用构建器构建它,则不需要@FeignClient 回退时也没有@Component 【参考方案1】:

我认为你混合了 2 种 feign 客户端初始化方法;声明式和手动初始化。你需要坚持一种方法。

如果您使用的是声明式初始化;您可以将@FeignClient 注释与下面的后备一起使用;

@FeignClient(value = "authenticationClient", url = "$feign.url", fallback = AuthenticationClientFallback.class)
public interface AuthenticationClient

您可以像这样在组件中自动装配 feign 客户端。

@Autowired
AuthenticationClient client;

如果您使用 feign 客户端的手动初始化并进行了一些自定义;那么您不必在 AuthenticationClient 类上使用 @FeignClient 注释。您可以像下面这样创建自定义的 feign 客户端;

@Autowired
AuthenticationClientFallback fallbackClient;

public AuthenticationClient getAuthenticationClient()
    
        return HystrixFeign.builder().contract(new SpringMvcContract())
                 .encoder(new JacksonEncoder())
                 .decoder(new JacksonDecoder())
                 .client(new OkHttpClient())
                 .logger(new Slf4jLogger(AuthenticationClient.class))
                 .logLevel(Logger.Level.FULL).target(AuthenticationClient.class, getTargetURL(), fallbackClient);
    

请注意,fallbackClient 对象作为参数传入 .target()。

更多详情请参考Spring cloud feigndocumentation

【讨论】:

以上是关于如果使用 Feign.Builder 手动创建 Feign Client,则不调用 Hystrix 回退方法的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在使用 SpringCloud OpenFeign 时为每个 Feign 实例创建不同的客户端?

Spring Cloud Feign 组成和配置

声明式HTTP客户端 - Spring Cloud OpenFeign

假装日志不起作用

如何使用数据创建摘要(Google 表格)

Maven 实战-手动创建Maven项目,使用Maven编译