3

我正在用Eureka,Zuul和FeignClient构建一个Spring Cloud项目(Brixton.M4和Spring Boot 1.3.1),我试图添加多租户支持(租户由子域:tenant1.myservice.com标识)。为此,我想以某种方式将原始子域传递给通过Feign从服务转发到另一个的请求,但我似乎无法找到正确的方式来执行此操作。Spring Cloud Netflix:通过RequestInterceptor将主机请求参数传递给FeignClient

我所拥有的是一个公开@RestController的客户端,它调用@FeignClient与我的后端进行通信,后端通过自己的@RestController向客户端公开服务器操作。使用相同的接口,我在服务器上@RestController

的@FeignClient:

@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 
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS) 
public CurrentTenant currentTenant() { 
    return new CurrentTenant(); 
} 

在服务器上,我使用的是应该抓住头值,并用它来定义该DB连接到休眠多租户提供商:

@Autowired 
private HttpServletRequest httpRequest; 

@Override 
public String resolveCurrentTenantIdentifier() { 
    return httpRequest.getHeader("TENANT"); 
} 

看来Feign对服务器的调用是在另一个线程中完成的,并且不在传入的请求范围内,所以我不确定如何传递该值。

当我在RequestInterceptor中对租户值进行硬编码时,它一切正常,因此我知道其余的工作正常。

我也看过很多关于Zuul“X-Forwaded-For”标题的文章,并且在服务器收到的请求中找不到它。我也尝试添加一个ZuulFilter来将主机名传递给下一个请求,但是我看到的是对ZuulFilter的原始请求被ZuulFilter拾取,我可以添加,但是当Feign请求被发送到后端服务时,即使我在zuul中映射它(我想这是有意的?)。

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

+0

就发现,假装跟踪项目,这似乎做同样的事情可能工作:https://github.com/ isthari/spring-cloud-feign-tracing –

回答

3

希望它对您有任何用处,但我们在Spring-Cloud-Sleuth中做的类似,但我们使用ThreadLocal在不同的库和方法(包括Feign + Hystrix)之间传递跨度。

这里是与突出显示的行,我们从线程本地检索跨度的例子: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

+0

Marcin,谢谢你的回答!我曾尝试使用Threadlocal,但我记得它没有工作,因为伪装执行似乎发生在另一个线程中,但我明天再试一次。 –

+1

如果您使用Feign与Hystrix,那么肯定会发生这种情况。我们通过两种方法解决了这个问题。 1)Hystrix的全局 - 自定义并发策略 - https:// github。com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixConcurrencyStrategy.java#L11 2)Custom只有Feign的方法https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/ Web /客户端/ TraceFeignClientAutoConfiguration.java#L92 –

+0

我终于得到它遵循您的自定义并发示例工作。我将租户值存储在可调用构造函数中,并将其设置回call()中的hystrix线程。非常感谢你的帮助 ! –