【问题标题】:Pass request headers to Ribbon IRule key parameter将请求标头传递给功能区 IRule 键参数
【发布时间】:2016-03-31 02:13:10
【问题描述】:

我有一个 Spring Cloud 应用程序,我正在按照 here in section Customizing the Ribbon Client 的说明自定义功能区客户端,我的 IRule 如下所示:

public class HeadersRule extends AbstractLoadBalancerRule {

public HeadersRule () {
}

public HeadersRule(ILoadBalancer lb) {
    this();
    this.setLoadBalancer(lb);
}

public Server choose(ILoadBalancer lb, Object key) {

     //I want the key to contain the headers from the request so I can decide choose the server by one of the headers

    }

我有一个休息控制器:

@RequestMapping("/")
public String hello(HttpServletRequest request, HttpServletResponse response) {

   //here I want to pass  the key parameter to ribbon

    return result;
}

我希望在我的 IRule 中通过其中一个标头的值来选择下一个服务器。 如何将标头传递给我的自定义 IRule 键参数?(通过 RestTemplate 或 Feign,或者如果您有另一个使用 Ribbon 的选项...)

编辑可能的方向

在 AbstractLoadBalancerAwareClient 类中

public T executeWithLoadBalancer(final S request, final IClientConfig requestConfig) throws ClientException {
    RequestSpecificRetryHandler handler = getRequestSpecificRetryHandler(request, requestConfig);
    LoadBalancerCommand<T> command = LoadBalancerCommand.<T>builder()
            .withLoadBalancerContext(this)
            .withRetryHandler(handler)
            .withLoadBalancerURI(request.getUri())
            .build();

构建 LoadBalancer 命令并省略:

.withServerLocator(request)

会完成这项工作的! 我可以从配置中重写这个方法,在 Spring RibbonClientConfiguration 类中我可以配置:

@Bean
@Lazy
@ConditionalOnMissingBean
public RestClient ribbonRestClient(IClientConfig config, ILoadBalancer loadBalancer) {
    RestClient client = new OverrideRestClient(config);
    client.setLoadBalancer(loadBalancer);
    Monitors.registerObject("Client_" + this.name, client);
    return client;
}

问题是同名的东西不起作用:

@Value("${ribbon.client.name}")
private String name = "client";

似乎应该用这个名称进行一些配置,因为我看到我的负载均衡器服务器列表由于某种原因总是空的,如果有人知道我应该如何配置这个属性我相信它可以解决问题.. .

【问题讨论】:

  • 功能区不知道当前请求。它也在另一个线程中运行。
  • 如果我可以将 IRule 选择函数的关键参数传递给其余模板,并将其传递给底层功能区,它将解决我只是不知道如何解决的问题......(也许将自定义拦截器添加到其余模板或覆盖另一个类,如负载均衡器...)
  • 这可能是要模仿的东西:github.com/jmnarloch/…
  • @spencergibb 请看我的编辑,也许你能想到解决办法!无论如何感谢您的帮助!

标签: spring-mvc spring-cloud netflix


【解决方案1】:

我对您的方法进行了一些修改以使其发挥作用: 除了获取ribbonRestClient bean,您还需要提供ribbonServerList bean。但不要使用 RibbonClientConfiguration 中定义的使用 ConfigurationBasedServerList 的 bean。这就是你得到一个空列表的原因。您可以定义服务器列表您的配置,或者,如果您更喜欢使用 eureka,则可以从 EurekaRibbonClientConfiguration 获取 bean:

@Bean
@ConditionalOnMissingBean
public ServerList<?> ribbonServerList(IClientConfig config) {
    DiscoveryEnabledNIWSServerList discoveryServerList = new DiscoveryEnabledNIWSServerList(
            config);
    DomainExtractingServerList serverList = new DomainExtractingServerList(
            discoveryServerList, config, this.approximateZoneFromHostname);
    return serverList;
}

这将动态填充您的服务器列表。 除此之外,请确保您用来覆盖ribbonRestClientBean 的配置文件没有被自动扫描。 这就是导致

@Value("${ribbon.client.name}")
private String name = "client";

在应用程序加载时尝试填充。要么将配置放在与你的主应用类不同的包中,要么将其排除在扫描之外

最后,不要忘记将@RibbonClient / @RibbonClients 添加到您的主类以指向覆盖的配置

@RibbonClients(defaultConfiguration = {my.non.autoScanned.MyRibbonClientConfiguration.class} ) 
@SpringBootApplication()
public class MyApp {

【讨论】:

    猜你喜欢
    • 2016-04-21
    • 2013-11-23
    • 1970-01-01
    • 2015-06-09
    • 1970-01-01
    • 2016-04-01
    • 2012-01-13
    • 1970-01-01
    • 2012-11-17
    相关资源
    最近更新 更多