如何微调 Spring Cloud Feign 客户端?

Posted

技术标签:

【中文标题】如何微调 Spring Cloud Feign 客户端?【英文标题】:How to fine-tune the Spring Cloud Feign client? 【发布时间】:2017-01-22 19:44:30 【问题描述】:

春云doc 说:

如果 Hystrix 在类路径上,默认情况下 Feign 会包装所有方法 带断路器。

    很好,但是如何配置 Hystrix 选项以忽略某些异常?我有一个将 HTTP 状态代码映射到异常的 ErrorDecoder 实现。如果我将@HystrixCommand 放在方法上,Feign 是否尊重这一点? 我们的要求是记录对依赖项发出的每个 HTTP 调用的各种详细信息。目前我有一个装饰的RestTemplate 可以做到这一点。根据我在代码中看到的内容以及 Dave Syer 的回答 here,Feign 不使用 RestTemplate。那么如何满足日志记录要求呢?界面 feign.Client 看起来很有希望,尽管我不完全确定是否可以使用。

【问题讨论】:

【参考方案1】:
    Feign 不支持@HystrixCommand,也不支持忽略异常。我的建议是禁用 feigns hystrix 集成 (feign.hystrix.enabled=false) 并在 feign 之外使用 hystrix。 Feign 支持RequestInterceptors,它会给你一个登录的地方。请参阅the docs 了解更多信息。

例子:

@FeignClient(name = "stores", configuration = StoreConfiguration.class)
public interface StoreClient 
    //..


@Configuration
public class StoreConfiguration 

    @Bean
    public LoggingRequestInterceptor loggingRequestInterceptor() 
        return new LoggingRequestInterceptor();
    

【讨论】:

谢谢,我会试试上面的。你觉得我开一个feign的改进请求支持HystrixCommand注解怎么样? 我不认为它会飞(feign 不使用 javanica,这是注释的来源),但要求能够设置忽略的异常是可以的(因为它没有实现无关紧要)。 嗯,可能需要在两个地方都完成工作,所以你没事。 好的,你的第一个建议有效,第二个无效。我需要记录通话的持续时间,RequestInterceptor 不允许我这样做。一切都是为了提出请求。【参考方案2】:

您可以编写 ErrorDecoder 并在您不希望触发断路器的异常上抛出 HystrixBadRequestException (https://github.com/Netflix/Hystrix/wiki/How-To-Use#error-propagation)

【讨论】:

谢谢。但是,我认为禁用 Feign hystrix 支持 (feign.hystrix.enabled=false) 并在调用方方法上使用 @HystrixCommand 更简单。这就是我现在正在做的事情。 是的,使用ignoreExceptions【参考方案3】:

在这种情况下,我们使用自己的 mime 类型来处理异常,因此即使是错误情况也会以 http 200 响应但拥有自己的 mime 类型。然后我们可以在错误 mime 类型的情况下拦截 200er 响应,并通过从响应错误代码反序列化重新抛出与服务器端相同的异常,而不会被回退捕获。这适用于 Feign 和一些 FeignBuildwr 魔术

【讨论】:

这种方法存在不止一个问题。错误情况返回 200 违反了 HTTP 规范。这也不是 mime 类型的用途。【参考方案4】:

就像@spencergibb 说的,Feign 现在不支持忽略异常,为此我开了一个enhancement request。 至于我的第二个要求,RequestInterceptor 并没有削减它,因为我需要响应时间,而RequestInterceptor 无法访问。我最终实现了feign.Client 并记录了execute 方法所花费的时间。大部分代码取自feign.Client.Default,可惜该类不是为扩展而设计的。然后我在FeignBuilder 中使用我的自定义客户端,如下所示:

@Bean
@Scope(SCOPE_PROTOTYPE)
public Feign.Builder feignBuilder() 
    return HystrixFeign.builder()
            .client(loggingEnabledFeignClient());


@Bean
Client loggingEnabledFeignClient() 
    return new LoggingEnabledFeignClient();

【讨论】:

以上是关于如何微调 Spring Cloud Feign 客户端?的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud Feign 调用过程分析

spring cloud中如何通过feign调整负载均衡规则

如何使用 spring-cloud-netflix 和 feign 编写集成测试

Spring-Cloud之Feign

如何使用 Spring Cloud 将 Hystrix 属性设置为 Feign 请求?

如何使用 Spring Cloud Feign 发布表单 URL 编码的数据