1
votes

Consider a simple controller

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;

@RestController
public class DtoController {

    private final WebClient client = WebClient.create("http://localhost:8081");

    @GetMapping("/booking")
    public Mono<MyDto> getDto() {
        return carsClient.get().uri("/myUrl")
                .retrieve()
                .bodyToMono(MyDto.class);
    }

}

A documentation tells that in spring web flux there are single IO thread and N workers (N - CPU core count). And worker threads are reused between Mono/Flux calls.

But when I run this application I see that in addition to spring flux spring web client also creates IO thread and N workers. So I got:

"Attach Listener"@11 046: RUNNING
"DestroyJavaVM"@9 089 in group "main": RUNNING
"Finalizer"@11 048: WAIT
"ObjectCleanerThread"@6 732 in group "main": WAIT
"reactor-http-nio-1"@6 711 in group "main": RUNNING
"reactor-http-nio-2"@6 713 in group "main": RUNNING
"reactor-http-nio-3"@6 715 in group "main": RUNNING
"reactor-http-nio-4"@6 714 in group "main": RUNNING
"Reference Handler"@11 049: WAIT
"RMI Scheduler(0)"@1 798: WAIT
"RMI TCP Accept-0"@1 288: RUNNING
"RMI TCP Accept-0"@1 445: RUNNING
"RMI TCP Accept-59098"@1 355: RUNNING
"Signal Dispatcher"@11 047: RUNNING
"SimplePauseDetectorThread_0"@6 329: SLEEPING
"Thread-15"@6 328: WAIT
"XNIO-1 Accept"@8 573 in group "main": RUNNING
"XNIO-1 I/O-1"@8 518 in group "main": RUNNING
"XNIO-1 I/O-2"@8 537 in group "main": RUNNING
"XNIO-1 I/O-3"@8 547 in group "main": RUNNING
"XNIO-1 I/O-4"@8 552 in group "main": RUNNING

Threads with reactor-http-nio prefix correspond to spring application, while XNIO to web flux client.

Is there a way to reuse workers between web client and application? And is it a good idea to reuse those threads?

1

1 Answers

4
votes

Is your server application running on top of Reactor Netty or maybe Undertow? XNIO threads are usually associated with Undertow. You can make sure of that by looking at the logs during application startup.

If that's the case, then this is the expected behavior since Reactor Netty and Undertow don't share client and server resources.

In recent versions of Spring Boot, client and server resources are automatically shared, when possible for Jetty and Reactor Netty.

As a side note, if you're using Spring Boot, you should try and create WebClient instances from a WebClient.Builder that you can get injected anywhere in your app. This will provide you with the expected defaults and custom configuration.