Ive discovered some strange behaviour where it appears WebClient + reactor-netty is creating up to hundreds of reactor-http-nio threads when we make parallel calls using WebClient, without performing any initial warmup. I've managed to reproduce this relatively easily with the following code where I submit tasks to an Executor service that uses the WebClient instance to call a remote service in parallel.
import org.junit.jupiter.api.Test;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Executors;
public class ParallelTest {
@Test
public void testBreakIt3() throws Exception {
final WebClient webClient = WebClient.builder()
.baseUrl("<the service>") // swap me
.build();
final ExecutorCompletionService service = new ExecutorCompletionService(Executors.newFixedThreadPool(5));
final int iterations = 300;
for (int i = 0; i < iterations; i++) {
service.submit(() -> {
webClient.get()
.uri("<the url>"). // swap me
.exchange()
.block();
return null;
});
}
int success = 0;
int errors = 0;
for (int i = 0; i < iterations; i++) {
try {
service.take().get();
++success;
} catch (Exception ex) {
++errors;
}
}
System.out.println("Errors: " + errors);
System.out.println("Success:" + success);
}
}
When DEBUG logging is enabled, we see many high range numbered reactor netty threads, e.g reactor-http-nio-45 reactor-http-nio-18
Attaching a profiler (Ive used Java Flight Recorder along with Intellij to inspect Java events), we notice many reactor-http-nio threads being started, well beyond the number we would expect based on our CPU.
If I change the above code to make a WebClient call before we enter the loop that makes many parallel calls, then we end up with a correct number of reactor threads (in this case, reactor-http-nio-1 through to reactor-http-nio-12).
If we use warmup()
method, the problem goes away.
HttpClient httpClient = HttpClient.create();
httpClient.warmup().block();
final WebClient webClient = WebClient.builder()
.baseUrl("<the url>")
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
Tested using: - spring-webflux 5.3.4 - reactor-netty 1.0.3
Comment From: violetagg
@gordz There should be exactly 12 (for your use case) running threads regardless of the number that they have in the name. Please check these: https://github.com/reactor/reactor-netty/pull/1426 https://github.com/reactor/reactor-netty/pull/1453
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: spring-projects-issues
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.