I have a service structure as follows: server (Eureka), property (eureka-client) and client (eureka-client).
The customer service makes a request for the service of property, using the feign. I have the LoadBalancer configured on both sides (property and client). If all services are running, calls and LoadBalancer work correctly. However, I started doing the part of the Circuitbreaker (Hystrix).
I just uploaded the server service (eureka) and the client service, to test the CircuitBreaker. When the customer service was making a request for the property service, the fallback was activated correctly, however, the exception thrown was different than expected. The exception I received was:
java.lang.RuntimeException: com.netflix.client.ClientException: Load balancer does not have available server for client: imovel-service
I expected to receive an exception of type 400+. What am I doing wrong?
server (Eureka Server)
@SpringBootApplication
@EnableEurekaServer
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
server application.yml
server:
port: ${PORT:8080}
spring:
application:
name: eureka-service
boot:
admin:
url: http://localhost:8090
eureka:
instance:
hostname: localhost
leaseRenewalIntervalInSeconds: 10
client:
registerWithEureka: false
fetchRegistry: true
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
management:
security:
enabled: false
Customer Service:
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableCircuitBreaker
@RibbonClient(name = "ribbon-configuration", configuration = RibbonConfiguration.class)
public class ClienteApplication {
public static void main(String[] args) {
SpringApplication.run(ClienteApplication.class, args);
}
@LoadBalanced
@Bean
RestTemplate restTemplate(){
return new RestTemplate();
}
}
@Configuration
public class FeignConfiguration {
int FIVE_SECONDS = 5000; // milliseconds
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
@Bean
public Request.Options options() {
return new Request.Options(FIVE_SECONDS, FIVE_SECONDS);
}
}
@FeignClient(value = "imovel-service", fallbackFactory = ImovelClientFallBackFactory.class)
public interface ImovelClient {
@GetMapping("/imovel")
List<Imovel> findAll();
@GetMapping("/imovel/{id}")
Imovel find(@PathVariable("id") Integer id);
}
@Component
public class ImovelClientFallBackFactory implements FallbackFactory<ImovelClient> {
@Override
public ImovelClient create(Throwable throwable) {
return new ImovelClientFallBack(throwable);
}
public class ImovelClientFallBack implements ImovelClient {
private final Throwable cause;
public ImovelClientFallBack(Throwable cause) {
this.cause = cause;
}
@Override
public List<Imovel> findAll() {
if (cause instanceof FeignException && ((FeignException) cause).status() == 404) {
throw new RuntimeException("Serviço indisponível!");
}
return null;
}
@Override
public Imovel find(Integer id) {
if (cause instanceof FeignException && ((FeignException) cause).status() == 404) { --aqui não vem 404, vem a exceção que comentei logo acima.
throw new RuntimeException("Serviço indisponível!");
}
return null;
}
}
}
CLIENT's application.yml
server:
port: ${PORT:8082}
#LOCALIZAÇÃO DO EUREKA SERVER
eureka:
client:
serviceUrl:
defaultZone: ${EUREKA_URI:http://localhost:8080/eureka}
instance:
preferIpAddress: true
spring:
application:
name: cliente-service
#CONFIGURAÇÃO DE FALLBACK DO FEIGN
feign:
hystrix:
enabled: true
imovel-service:
ribbon:
MaxAutoRetries: 3
retryableStatusCodes: 404
The IMOVEL service has the same settings except application.yml
server:
port: ${PORT:8081}
eureka:
client:
serviceUrl:
defaultZone: ${EUREKA_URI:http://localhost:8080/eureka}
instance:
preferIpAddress: true
spring:
application:
name: imovel-service
Why am I getting the LoadBalancer exception instead of 404?