Spring Cloud Netflix:通过RequestInterceptor将主机请求参数传递给FeignClient

时间:2015-12-29 12:10:59

标签: spring-mvc spring-boot spring-cloud netflix-zuul netflix-feign

我正在与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(我猜这是有意的?)。

我不确定下一步是什么,并希望得到一些建议。

1 个答案:

答案 0 :(得分:3)

希望它对您有用,但我们在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