Spring Cloud Netflix:通过 RequestInterceptor 将主机请求参数传递给 FeignClient
Posted
技术标签:
【中文标题】Spring Cloud Netflix:通过 RequestInterceptor 将主机请求参数传递给 FeignClient【英文标题】:Spring Cloud Netflix : Passing host request parameter via RequestInterceptor to FeignClient 【发布时间】:2016-04-03 07:44:38 【问题描述】:我正在使用 Eureka、Zuul 和 FeignClient 构建一个 Spring Cloud 项目(带有 Spring Boot 1.3.1 的 Brixton.M4),我正在尝试添加多租户支持(租户由子域标识:tenant1.myservice.com)。为此,我想以某种方式将原始子域与通过 Feign 从服务转发到另一个服务的请求一起传递,但我似乎无法找到正确的方法。
我有一个客户端,它公开一个@RestController,它调用一个@FeignClient 来与我的后端通信,后端通过它自己的@RestController 向客户端公开服务器操作。
@FeignClient 使用与服务器上我的@RestController 相同的接口:
@FeignClient(name = "product")
public interface ProductService extends IProductService
我目前要做的是在 RequestInterceptor 中设置一个标头:
@Component
public class MultiTenancyRequestInterceptor implements RequestInterceptor
private CurrentTenantProvider currentTenantProvider;
@Autowired
public MultiTenancyRequestInterceptor(CurrentTenantProvider currentTenantProvider)
this.currentTenantProvider = currentTenantProvider;
@Override
public void apply(RequestTemplate template)
try
template.header("TENANT", currentTenantProvider.getTenant());
catch (Exception e)
// "oops"
我的提供者类是一个简单的组件,我试图在其中注入一个请求/会话范围 bean:
@Component
public class CurrentTenantProvider
@Autowired
private CurrentTenant currentTenant;
//...
bean(我尝试了会话和请求范围):
@Bean
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public CurrentTenant currentTenant()
return new CurrentTenant();
在服务器上,我使用 Hibernate 多租户提供程序,它应该捕获标头值并使用它来定义要连接到哪个数据库:
@Autowired
private HttpServletRequest httpRequest;
@Override
public String resolveCurrentTenantIdentifier()
return httpRequest.getHeader("TENANT");
似乎对服务器的 Feign 调用是在另一个线程中完成的,并且超出了传入的请求范围,所以我不确定如何传递该值。
当我在 RequestInterceptor 中对租户值进行硬编码时,一切正常,因此我知道其余的工作正常。
我还查看了许多其他关于 Zuul “X-Forwaded-For” 标头的帖子,但在服务器收到的请求中找不到它。我也尝试添加一个 ZuulFilter 以将主机名传递给下一个请求,但我看到的是 ZuulFilter 接收了对客户端的原始请求,我可以添加但当 Feign 请求发送到后端服务时不能添加,即使我在 zuul 中映射它(我猜这是有意的?)。
我不太确定下一步是什么,希望能得到一些建议。
【问题讨论】:
刚刚发现 feign tracking 项目似乎做了类似的事情可能会起作用:github.com/isthari/spring-cloud-feign-tracing 【参考方案1】:希望它对您有用,但我们在 Spring-Cloud-Sleuth 中做类似的事情,但我们使用 ThreadLocal 在不同的库和方法(包括 Feign + Hystrix)之间传递跨度。
这是一个突出显示的示例,我们从线程本地检索 Span:https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceFeignClientAutoConfiguration.java#L123
【讨论】:
Marcin,感谢您的回答!我确实尝试过使用 Threadlocal,但我记得它也不起作用,因为假装执行似乎发生在不同的线程中,但我明天再试一次。 如果你将 Feign 与 Hystrix 一起使用,那么肯定会发生这种情况。我们通过两种方法解决了这个问题。 1) Hystrix 的全局 - 自定义并发策略 - github.com/spring-cloud/spring-cloud-sleuth/blob/master/… 2) 仅适用于 Feign 的自定义方法 github.com/spring-cloud/spring-cloud-sleuth/blob/master/… 我终于按照你的自定义并发示例让它工作了。我将租户值存储在可调用构造函数中,并在 call() 中将其设置回 hystrix 线程。非常感谢您的帮助! 太棒了!这正是需要做的 :) 这就是在线程之间传递事物的方式。 如果你问这个问题,Sleuth 中的 feign Code 已经发生了很大变化。无论如何,对于启动 1.4,一切都应该正常以上是关于Spring Cloud Netflix:通过 RequestInterceptor 将主机请求参数传递给 FeignClient的主要内容,如果未能解决你的问题,请参考以下文章
spring-cloud-starter-eureka-server 和 spring-cloud-starter-netflix-eureka-server的区别
Spring Cloud Netflix:通过 RequestInterceptor 将主机请求参数传递给 FeignClient
Spring Cloud 入门教程:和RabbitMQ的整合 -- 消息总线Spring Cloud Netflix Bus