I have a Spring Cloud application and I am customizing the ribbon client as explained here in section Customizing the Ribbon Client my IRule looks like this:
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
}
I have a Rest Controller:
@RequestMapping("/")
public String hello(HttpServletRequest request, HttpServletResponse response) {
//here I want to pass the key parameter to ribbon
return result;
}
I want in my IRule to choose the next server by the value of one of the headers. How can I pass the headers to my custom IRule key parameter ?(via RestTemplate or Feign or if you have another option that uses Ribbon...)
Edit Possible Direction
in 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();
building the LoadBalancer command and omitting the:
.withServerLocator(request)
would have done the job! I can override this method from the configuration, in Spring RibbonClientConfiguration class I can configure:
@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;
}
The problem is that something with the name is not working:
@Value("${ribbon.client.name}")
private String name = "client";
There seems to be some configuration that should be done with this name, because I see that my loadbalancer server list is always empty for some reason, if someone knows how should I configure this property I believe it can solve the problem...
I took your approach with some modifications to get it to work: Besides for taking the ribbonRestClient bean you need to provide the ribbonServerList bean. but don't take the bean defined in RibbonClientConfiguration which uses ConfigurationBasedServerList. that's the reason you're getting an empty list. you can either define the server list your configuration or, if you prefer using eureka take the bean from EurekaRibbonClientConfiguration instead:
@Bean
@ConditionalOnMissingBean
public ServerList<?> ribbonServerList(IClientConfig config) {
DiscoveryEnabledNIWSServerList discoveryServerList = new DiscoveryEnabledNIWSServerList(
config);
DomainExtractingServerList serverList = new DomainExtractingServerList(
discoveryServerList, config, this.approximateZoneFromHostname);
return serverList;
}
that will dynamically populate your server list. besides for that, make sure the configuration file you're using to override the ribbonRestClientBean is not auto-scanned. that's what's causing the
@Value("${ribbon.client.name}")
private String name = "client";
to try and populate upon application loading. either put the configuration in a different package that your main app class or exclude it from scanning
Lastly, don't forget to add the @RibbonClient / @RibbonClients to your main class to point to the overridden configuration
@RibbonClients(defaultConfiguration = {my.non.autoScanned.MyRibbonClientConfiguration.class} )
@SpringBootApplication()
public class MyApp {
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With