将请求 headers 传递给 Ribbon IRule 关键参数
Pass request headers to Ribbon IRule key parameter
我有一个 Spring 云应用程序,我正在按照说明自定义功能区客户端 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 中通过 headers 之一的值选择下一个服务器。
如何将 headers 传递给我的自定义 IRule 键参数?(通过 RestTemplate 或 Feign,或者如果您有另一个使用 Ribbon 的选项...)
编辑可能的方向
在class 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 class 我可以配置:
@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";
似乎有一些配置应该用这个名字完成,因为我看到我的负载均衡器服务器列表出于某种原因总是空的,如果有人知道我应该如何配置这个 属性 我相信它可以解决问题...
我对您的方法进行了一些修改以使其起作用:
除了获取 ribbonRestClient bean 之外,您还需要提供 ribbonServerList bean。但不要采用在使用 ConfigurationBasedServerList 的 RibbonClientConfiguration 中定义的 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 的配置文件不是 auto-scanned。
这就是导致
@Value("${ribbon.client.name}")
private String name = "client";
尝试在应用程序加载时填充。将配置放在与主应用程序不同的包中 class 或将其从扫描中排除
最后,不要忘记将 @RibbonClient / @RibbonClients 添加到您的 main class 以指向覆盖的配置
@RibbonClients(defaultConfiguration = {my.non.autoScanned.MyRibbonClientConfiguration.class} )
@SpringBootApplication()
public class MyApp {
我有一个 Spring 云应用程序,我正在按照说明自定义功能区客户端 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 中通过 headers 之一的值选择下一个服务器。 如何将 headers 传递给我的自定义 IRule 键参数?(通过 RestTemplate 或 Feign,或者如果您有另一个使用 Ribbon 的选项...)
编辑可能的方向
在class 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 class 我可以配置:
@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";
似乎有一些配置应该用这个名字完成,因为我看到我的负载均衡器服务器列表出于某种原因总是空的,如果有人知道我应该如何配置这个 属性 我相信它可以解决问题...
我对您的方法进行了一些修改以使其起作用: 除了获取 ribbonRestClient bean 之外,您还需要提供 ribbonServerList bean。但不要采用在使用 ConfigurationBasedServerList 的 RibbonClientConfiguration 中定义的 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 的配置文件不是 auto-scanned。 这就是导致
@Value("${ribbon.client.name}")
private String name = "client";
尝试在应用程序加载时填充。将配置放在与主应用程序不同的包中 class 或将其从扫描中排除
最后,不要忘记将 @RibbonClient / @RibbonClients 添加到您的 main class 以指向覆盖的配置
@RibbonClients(defaultConfiguration = {my.non.autoScanned.MyRibbonClientConfiguration.class} )
@SpringBootApplication()
public class MyApp {