将 Zuul、Hystrix(和 Feign)与 Spring Cloud HATEOAS 一起使用时如何转发标头?

Posted

技术标签:

【中文标题】将 Zuul、Hystrix(和 Feign)与 Spring Cloud HATEOAS 一起使用时如何转发标头?【英文标题】:How to forward headers when using Zuul, Hystrix (and Feign) with Spring Cloud HATEOAS? 【发布时间】:2019-08-16 19:54:51 【问题描述】:

上下文

我的微服务应用基于spring-cloud:在两个微服务前面配置了一个zuul网关:service-aservice-b.

我的一个 API 要求 service-a 请求 service-b;我为此使用feign

Zuul 向服务发送 X-FORWARDED-* 标头,以便它们正确重写 HATEOAS 链接(当服务配置为 ForwardedHeaderFilter 时)。

我的问题是服务使用Feign 相互通信,这依赖于HystrixHystrix 为每个请求创建一个新线程(我们不使用 SEMAPHORE 配置),因此 Spring 的 RequestContextHolder 中的请求在 service-a 的 Feign 请求中丢失service-b,由于原始请求丢失,我无法再使用feign 拦截器丰富feign 请求。

一些潜在的解决方案

Spring现在直接支持转发授权令牌,参数hystrix.shareSecurityContext: true

没有任何“开箱即用”的配置可以让 Hystrix 在线程之间共享请求。

解决方案可能是implement my own HystrixConcurrencyStrategy,它是 netflix.hystrix 中的一个类。 我最新的发现是这个Pull Request 已经发送到spring-cloud-netflix,但遗憾的是没有集成。

我可以尝试复制Pull请求的代码,并创建一个bean,就像“eacdy”写的那样:

@Bean
public RequestAttributeHystrixConcurrencyStrategy hystrixRequestAutoConfiguration() 
    return new RequestAttributeHystrixConcurrencyStrategy();

有没有更简单的解决方案将来自Zuul 的标头转发到Hystrix

我想在使用ZuulHystrixHATEOAS 相互通信的微服务时,我正在尝试做的事情是非常标准的,所以也许已经存在一些东西(而且我没找到)?

谢谢!

【问题讨论】:

【参考方案1】:

我认为这是很常见的事情,但经过大量研究,我找不到一种方法来自动转发 X-FORWARDED-* 标头与 FeignHystrix

所以,我寻找了另一种解决方案,它有效且非常干净:

Feign客户端从service-aservice-b,我声明了一个具体的配置“ServiceBFeignConfig”,除了转发token,还要添加与网关对应的X-Forwarded-* 标头:
@Configuration
public class ServiceBFeignConfig 

    @Autowired
    private ApplicationProperties applicationProperties;

    @Bean
    public RequestInterceptor requestTokenBearerInterceptor() 
        return new RequestInterceptor() 
            @Override
            public void apply(RequestTemplate requestTemplate) 
                OAuth2AuthenticationDetails details =
                        (OAuth2AuthenticationDetails) SecurityContextHolder.getContext().getAuthentication().getDetails();
                requestTemplate.header("Authorization", "bearer " + details.getTokenValue());

                if (applicationProperties.getFeign().getGatewayEnabled()) 
                    requestTemplate.header("X-Forwarded-Host", applicationProperties.getFeign().getGatewayHost());
                    requestTemplate.header("X-Forwarded-Port", applicationProperties.getFeign().getGatewayPort());
                    requestTemplate.header("X-Forwarded-Proto", applicationProperties.getFeign().getGatewayProtocol());
                    requestTemplate.header("X-Forwarded-Prefix", applicationProperties.getFeign().getServiceBPrefix());
                
            
        ;
    


您可以看到在属性文件中配置了网关主机和端口(在我的例子中由Spring Cloud Config 提供服务)。 service-b 前缀也在这些文件中设置。

只有在属性文件中设置了“gatewayEnabled”属性时才会添加这些标头。

你必须从 Spring Boot 的组件扫描中忽略这个配置,即使它需要 @Configuration 注释,所以把它放在一个“ignorescan”包中,在你的主 Spring boot 类上,使用:
@ComponentScan(basePackages =  "com.myservice" , excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "com.myservice.ignorescan.*"))

最后,如果您将 gatewayEnabled 设置为 true,则会添加 Forward 标头,并且对网关的 API 调用会获得正确的 HATEOAS 链接。

【讨论】:

以上是关于将 Zuul、Hystrix(和 Feign)与 Spring Cloud HATEOAS 一起使用时如何转发标头?的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud中五大神兽总结(Eureka/Ribbon/Feign/Hystrix/zuul)

springcloud微服务实战:Eureka+Zuul+Feign/Ribbon+Hystrix Turbine+SpringConfig+sleuth+zipkin

Eureka+Feign+Ribbon+Zuul+Hystrix+Config+Bus构建一套SpringCloud项目

使用zuul、eureka、feign时如何减少延迟

将 Netflix Zuul 与 Netflix Hystrix 相结合

微服务SpringCloud之服务网关zuul一