将请求标头传递给Ribbon IRule密钥参数

时间:2015-12-24 17:26:50

标签: spring-mvc spring-cloud netflix

我有一个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

    }

我有一个Rest Controller:

@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";

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

1 个答案:

答案 0 :(得分:4)

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

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

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

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

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

最后,不要忘记将@RibbonClient / @RibbonClients添加到主类中以指向重写的配置

System.Windows.Resources.StreamResourceInfo imageInfo = System.Windows.Application.GetResourceStream(primaryMarkerSymbol.UriSource);
_primaryMarkerSymbol = Image.FromStream(imageInfo.Stream);