We're migrating the Spring Boot from 2 to 3 and also getting rid off Netflix Ribbon. We're experiencing an issue while trying to discover a service using Consul. If we rollback to Spring Boot 2 + Netflix Ribbon, it works with no problem, so we discarded any connectivity issue.
Logging errors:
RoundRobinLoadBalancer|No servers available for service: cachedavailability-integrations-service
ReactorLoadBalancerExchangeFilterFunction|LoadBalancer does not contain an instance for the service cachedavailability-integrations-service
Communication error with uri: http://cachedavailability-integrations-service/testing org.springframework.web.reactive.function.client.WebClientResponseException$ServiceUnavailable: 503 Service Unavailable from UNKNOWN
at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:336)
Suppressed: The stacktrace has been enhanced by Reactor, refer to additional information below:
Error has been observed at the following site(s):
*__checkpoint ⇢ 503 SERVICE_UNAVAILABLE from GET http://cachedavailability-integrations-service/testing [DefaultWebClient]
Consul interface
- The service "si-manager" is the one trying to discover and access the "cachedavailability" one.
- It is registering well, but not discovering the other services registered when using WebClient bean.
We have already tried many ways, such as:
- https://docs.spring.io/spring-cloud-consul/docs/current/reference/html/#using-the-discoveryclient
- Service discovery with spring webflux WebClient
- Configuring spring-cloud loadbalancer without autoconfiguration
Sample
Main Class
@org.springframework.cloud.client.discovery.EnableDiscoveryClient
public class MainApplication {...}
WebClient config
@Bean(name = "webClientConsulAvailability")
public WebClient webClientConsulAvailability(
WebClient.Builder webClientBuilder,
ReactorLoadBalancerExchangeFilterFunction lbFunction,
ExchangeFilterFunction logFilter
) {
return webClientBuilder
.filter(lbFunction)
.filter(logFilter)
.build();
}
bootstrap.yml
spring:
application:
name: si-manager-service
profiles:
active: ${SPRING_PROFILES_ACTIVE:local}
cloud:
consul:
host: localhost
port: 8500
enabled: true
discovery:
serviceName: ${spring.application.name}
instanceId: ${spring.application.name}8500
enabled: true
# Register as a service in consul.
register: true
registerHealthCheck: true
Dependencies
Consul version: v1.15.3
Usage example:
webClientConsulAvailability.get()
.uri("http://cachedavailability-integrations-service/testing")
.retrieve()
.bodyToFlux(MyDTO.class)
.doOnError(e -> {
if (isErrorLogLevel(e)) {
log.error(COMMUNICATION_ERROR_WITH_URI + uri, e);
} else {
log.warn(COMMUNICATION_ERROR_WITH_URI + uri, e);
}
})
.onErrorResume(e -> Flux.empty());
Fixed with code below.