Spring cloud load-balancer drops instances after cache refresh

406 Views Asked by At

I have a need to save Spring Cloud Gateway routes within a database and to do this we send a web request using the WebClient to another microservice. I'm using Eureka for service discovery and want the WebClient to use discovery instance names instead of explicit URLs and I've therefore utilised the @LoadBalanced annotation on the bean method:

    @Bean
    public WebClient loadBalancedWebClientBuilder(WebClient.Builder builder) {
        return builder
                .exchangeStrategies(exchangeStrategies())
                .build();
    }

    @Bean
    @LoadBalanced
    WebClient.Builder builder() {
        return WebClient.builder();
    }

    private ExchangeStrategies exchangeStrategies() {
        return ExchangeStrategies.builder()
                .codecs(clientCodecConfigurer -> {
                    clientCodecConfigurer.defaultCodecs().jackson2JsonEncoder(getEncoder());
                    clientCodecConfigurer.defaultCodecs().jackson2JsonDecoder(getDecoder());
                }).build();
    }

This all works on start-up and for the default 35s cache time - i.e. the webClient discovers the required 'saveToDatabase' service instance and sends the request.

On each eventPublisher.publishEvent(new RefreshRoutesEvent(this)) a call is made to the same downstream microservice (via the WebClient) to retrieve all saved routes. Again this works initially, but after the default 35seconds the load balancer cache seems to be cleared and the downstream service id can no longer be found:

WARN  o.s.c.l.core.RoundRobinLoadBalancer - No servers available for service: QUERY-SERVICE

I have confirmed it is the cache refresh purging the cache and not re-acquiring the instances by setting

spring:
  application:
    name: my-gateway
  cloud:
    loadbalancer:
      cache:
        enabled: true
        ttl: 240s
      health-check:
        refetch-instances: true
      ribbon:
        enabled: false
    gateway:
       ...

I've struggled with this for days now and cannot find/ see where or why the cache is not being updated, only purged. Adding specific @LoadBalancerClient() configuration as below makes no difference.

    @Bean
    public ServiceInstanceListSupplier instanceSupplier(ConfigurableApplicationContext context) {
        return ServiceInstanceListSupplier.builder()
                .withDiscoveryClient()
                .withHealthChecks()
                .withCaching()
                .withRetryAwareness()
                .build(context);
    }

Clearly this must work for other people, so what am I missing?!

Thanks.

0

There are 0 best solutions below