I want to use Eureka client with spring-cloud-starter-loadbalancer
. But when I added configuration I get error. When I remove @LoadBalancerClient(name = "mail-service", configuration = LoadBalancerConfiguration.class)
and LoadBalancerConfiguration
class configuration it's working fine. I tried this code:
@FeignClient(name = "mail-service")
@LoadBalancerClient(name = "mail-service", configuration = LoadBalancerConfiguration.class)
public interface EmailClient {
@RequestMapping(method = RequestMethod.POST, value = "/engine/emails/register")
void setUserRegistration(CreateUserDTO createUserDTO);
}
@Configuration
public class LoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withBlockingDiscoveryClient()
.withSameInstancePreference()
.withHealthChecks()
.build(context);
}
}
application.yml:
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: basic
eureka:
client:
serviceUrl:
defaultZone: ${EUREKA_URI:http://localhost:8761/eureka}
fetchRegistry: true
healthcheck:
enabled: true
instance:
preferIpAddress: true
leaseRenewalIntervalInSeconds: 10
POM.xml dependencies
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.eureka</groupId>
<artifactId>eureka-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
I get this error when I have only one target service.
[503] during [POST] to [http://mail-service/engine/emails/register] [EmailClient#setUserRegistration(CreateUserDTO)]: [Load balancer does not contain an instance for the service mail-service]
I use Release Train Version: 2020.0.3
Do you know what could be the problem?
Any application using load balancer should follow the below order
Any application relies on information from a service registry (i.e. Eureka). Until the application is registered with it's instances by the serviceId , the Eureka server will not be able to pick that instance while load-balancing.
In the code you have shared, the bean ServiceInstanceListSupplier is created in the configuration class along with the health checks ( .withHealthChecks() ). This is causing the application to fail as service has not been registered yet.
Also, the LoadBalancer config should not be in a @Configuration-annotated class instead, it should be a class passed for config via @LoadBalancerClient or @LoadBalancerClients annotation, as described here.
The only bean you need to instantiate is the ServiceInstanceListSupplier (if you add spring-cloud-starter-loadbalancer, LoadBalancerClientFactory etc. will be instantiated by the starter itself).
So your LoadBalancer configuration class should look like code below. It should not be in the @Configuration class:
public class LoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier instanceSupplier(ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withHealthChecks()
.build(context);
}
}
As explained in this link, the actual @Configuration class , will have the following annotation: @LoadBalancerClients(defaultConfiguration = LoadBalancerConfiguration .class).
Then, if you enable health-checks in the instances, it should work without any issues.