I'm trying to make PoC program using Spring's Cloud load balancer
for Feign
client.
I have Feign:
@FeignClient(value = "eisec2")
public interface Eisec2Client {
@GetMapping(path = "base1/path/{number}", consumes = MediaType.APPLICATION_XML_VALUE)
String getCaller(@PathVariable("number") String cli);
@RequestMapping(path = "status", method = RequestMethod.GET)
CallDetails getStatus();
}
Load Balancing config:
@RequiredArgsConstructor
@EnableFeignClients("com.frequentis.isec_server.client")
@LoadBalancerClient(value = "eisec2", configuration = LoadBalancerConfiguration.class)
public class FeignEisec2InstanceBalancingConfiguration {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
and LoadBalancerConfiguration
:
public class LoadBalancerConfiguration {
@Bean // <-- "works" with bean commented out
public ServiceInstanceListSupplier instanceSupplier(ConfigurableApplicationContext context, DiscoveryClient discoveryClient) {
return ServiceInstanceListSupplier.builder()
.withHints()
.withBlockingDiscoveryClient()
.withBlockingHealthChecks(new RestTemplate())
.build(context);
}
@Bean
ReactorLoadBalancer<ServiceInstance> rrLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
final RoundRobinLoadBalancer roundRobinLoadBalancer = new RoundRobinLoadBalancer(
loadBalancerClientFactory.getLazyProvider(
name,
ServiceInstanceListSupplier.class),
name);
return roundRobinLoadBalancer;
}
}
mine application.properties:
spring.application.name=balanced-server
spring.cloud.loadbalancer.enabled=true
spring.cloud.discovery.client.simple.instances.eisec2[1].uri=http://localhost:6090/eisec/1
spring.cloud.discovery.client.simple.instances.eisec2[0].uri=http://10.16.207.***:6090/eisec/1
spring.liquibase.enabled=false
server.http2.enabled=false
what I found out: it only works with ServiceInstanceListSupplier commented out, but only uses first instance defined in prop file ;D
When I uncommentd 'ServiceInstanceListSupplier' @Bean it'll
2024-06-01T18:30:17.318+02:00 WARN 9116 --- [balanced-server] [ parallel-2] o.s.c.l.core.RoundRobinLoadBalancer : No servers available for service: eisec2
2024-06-01T18:30:17.319+02:00 WARN 9116 --- [balanced-server] [nio-8080-exec-1] RetryableFeignBlockingLoadBalancerClient : Service instance was not resolved, executing the original request
2024-06-01T18:30:18.555+02:00 WARN 9116 --- [balanced-server] [nio-8080-exec-1] o.s.c.l.core.RoundRobinLoadBalancer : No servers available for service: eisec2
2024-06-01T18:30:18.555+02:00 WARN 9116 --- [balanced-server] [nio-8080-exec-1] RetryableFeignBlockingLoadBalancerClient : Service instance was not resolved, executing the original request
..and yes, output is doubled, I don't know why.
When I use non-blocking ServiceInstanceListSupplier
such:
ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withHealthChecks()
.build(context);
it will fail on:
No qualifying bean of type 'org.springframework.cloud.client.discovery.ReactiveDiscoveryClient' available
but I don't want to use reactor in this project..
DiscoveryClient
seems to read properties correctly:
In the triage, I found the configuration for which it interchanged desired service name )eisec2) for hosts configured in prop file and it was trying to find configuration for those hosts saying it can't find it. Upside down and never working except that one case when it doesn't load balance just contacts the first defined instance.
Also remark on the documentation for this otherwise handy and interesting feature: weak. So weak, I was putting all this together just to be able to make some testing a half day from various "not working" posts. I'll write some article showcasing this feature for Feign as soon as I'll make it work for me, but this is sad state anyway.
Question is, how to make it load-balance?
Spring Boot parent: v.3.2.6
Spring Cloud: v.2023.0.1