0

I followed this guide to implement a simple client-side load balancer in a Spring Boot application. Below is the code:

@RestController
class MyController(
    val loadBalancedWebClientBuilder: WebClient.Builder
) { 
    private fun makeRequest() {
        loadBalancedWebClientBuilder.build().post()
                .uri(URI("http://my-service/endpoint"))
                .body(BodyInserters.fromValue("{ \"data\" = \"data\" }"))
                .retrieve()
                .bodyToMono(String::class.java)
                .block()
    }
}

Here is the WebClient configuration:

@Configuration
@LoadBalancerClient(name = "my-service", configuration = [LoadBalancerConfig::class])
class WebClientConfig {
    @LoadBalanced
    @Bean
    fun webClientBuilder(): WebClient.Builder {
        return WebClient.builder()
    }
}

And the load balancer configuration:

class LoadBalancerConfig {
    @Bean
    @Primary
    fun serviceInstanceListSupplier(): ServiceInstanceListSupplier {
        return ServiceInstanceListSupplerImpl("my-service")
    }
}

class ServiceInstanceListSupplerImpl(private val serviceId: String) : ServiceInstanceListSupplier {
    override fun getServiceId(): String {
        return serviceId
    }

    override fun get(): Flux<List<ServiceInstance>> {
        return Flux.just(listOf("http://localhost").mapIndexed { index, s ->
            DefaultServiceInstance(index.toString(), serviceId, s, 8088, true) })
    }

}

Finally, in the configuration file I have the below:

spring:
  cloud:
    discovery:
      client:
        simple:
          instances:
            my-service[0].uri: http://localhost:8088

When running the above, the following exception gets thrown:

org.springframework.web.reactive.function.client.WebClientRequestException: Failed to resolve 'my-service' after 4 queries ; nested exception is java.net.UnknownHostException: Failed to resolve 'my-service' after 4 queries 
    at org.springframework.web.reactive.function.client.ExchangeFunctions$DefaultExchangeFunction.lambda$wrapException$9(ExchangeFunctions.java:141) ~[spring-webflux-5.3.24.jar:5.3.24]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    *__checkpoint ⇢ Request to POST http://my-service/endpoint [DefaultWebClient]
Original Stack Trace:
        at org.springframework.web.reactive.function.client.ExchangeFunctions$DefaultExchangeFunction.lambda$wrapException$9(ExchangeFunctions.java:141) ~[spring-webflux-5.3.24.jar:5.3.24]
        at reactor.core.publisher.MonoErrorSupplied.subscribe(MonoErrorSupplied.java:55) ~[reactor-core-3.4.25.jar:3.4.25]
        at reactor.core.publisher.Mono.subscribe(Mono.java:4490) ~[reactor-core-3.4.25.jar:3.4.25]
        at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103) ~[reactor-core-3.4.25.jar:3.4.25]
        at reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:222) ~[reactor-core-3.4.25.jar:3.4.25]
        at reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:222) ~[reactor-core-3.4.25.jar:3.4.25]
        at reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:222) ~[reactor-core-3.4.25.jar:3.4.25]
        at reactor.core.publisher.MonoNext$NextSubscriber.onError(MonoNext.java:93) ~[reactor-core-3.4.25.jar:3.4.25]
        at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onError(MonoFlatMapMany.java:204) ~[reactor-core-3.4.25.jar:3.4.25]
        at reactor.core.publisher.SerializedSubscriber.onError(SerializedSubscriber.java:124) ~[reactor-core-3.4.25.jar:3.4.25]
        ...
        

Any clue what might be wrong?

Vlad
  • 844
  • 1
  • 12
  • 22
  • What service discovery are you using? – spencergibb Feb 07 '23 at 17:14
  • SimpleDiscoveryClient, I added the configuration to the question. Perhaps I'm missing something there? – Vlad Feb 07 '23 at 17:22
  • But you have overridden the service instance list supplier, so simple discovery won't have any effect. Have you put a breakpoint in ServiceInstanceListSupplerImpl? – spencergibb Feb 07 '23 at 17:36
  • Yes, but for some reason the execution never reaches it. I tried tens of different configuration options (also without SimpleDiscoveryClient config), but none of them worked. Execution always reaches WebClientConfig, but never makes it to LoadBalancerConfig for some reason. Any idea why this happens? – Vlad Feb 07 '23 at 19:07
  • Not without a full sample that reproduces the problem. – spencergibb Feb 07 '23 at 21:43
  • @Vlad, if you want us to take a closer look at it, please create a GitHub issue at https://github.com/spring-cloud/spring-cloud-commons along with a sample that reproduces the issue. – OlgaMaciaszek Feb 08 '23 at 14:50
  • Thanks for offering to help. I'll do a bit more trial and error and post an issue if nothing will work. Btw, the issue above happens when I run the unit tests; do you happen to have any example of unit tests for the load balancer? – Vlad Feb 08 '23 at 15:12

0 Answers0