What are the internal details when using WebClient
What are the internal details of using WebClient? I believe many inexperienced people are helpless about this. For this reason, this article summarizes the causes and solutions of the problem. Through this article, I hope you can solve this problem.
Some of the internals of WebClient default to global resources
By default, all instances of WebClient share global Reactor-Netty resources contained in Reactor. netty. http.HttpResources. Resources specifically refer to event loop processing thread pool (event loop group) and connection management pool (http connection pool).
This is the recommended pattern for Spring, as the reuse event loop thread pool is preferred for concurrency tuning.
The default event loop processing thread pool in global resources contains 12 threads. The connection pool supports a maximum of 500 connections by default, and when the maximum link is reached, the request to obtain the link is buffered using an unbounded queue, and a timeout is reported if the link is not obtained for more than 45000 ms.
Note: Because links in the connection pool are domain-insensitive, if some domain names take a long time to respond, they may keep links unreleased, which may affect requests from other domain names.
At this point, you can customize resources to avoid using global resources:
@Beanpublic ReactorResourceFactory resourceFactory() { ReactorResourceFactory factory = new ReactorResourceFactory(); factory.setUseGlobalResources(false); return factory;}
@Beanpublic WebClient webClient() {
Function mapper = client -> { // Further customizations... };
ClientHttpConnector connector = new ReactorClientHttpConnector(resourceFactory(), mapper);
return WebClient.builder().clientConnector(connector).build(); }
However, this would result in the event processing thread pool not being reused.
Default IO thread executes callbacks
WebClient uses Netty internally to implement http client calls by default. Here, IO threads are actually IO threads of netty, while IO threads of netty clients are not recommended to do time-consuming operations, because IO threads are used to train data registered to channels on select in turn. If blocked, read and write requests of other channels will not be processed in time. Therefore, if the logic in the consumer is time-consuming, it is recommended to switch from the IO thread to another thread to do it.
So how do you switch that? You can use publishOn to switch IO threads to a custom thread pool for processing:
resp.publishOn(Scheduler.elastic())//Switch to the thread pool corresponding to Scheduler.elastic() .onErrorMap(throwable -> { System.out.println("onErrorMap:" + throwable.getLocalizedMessage()); return throwable; }).subscribe(s -> System.out.println("result:" + Thread.currentThread().getName() + " " + s)); timeout related configuration
timeout for establishing link with server
HttpClient httpClient = HttpClient.create() .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);
WebClient webClient = WebClient.builder() .clientConnector(new ReactorClientHttpConnector(httpClient)) .build();
Timed out reading data from server
HttpClient httpClient = HttpClient.create() .doOnConnected(conn -> conn .addHandlerLast(new ReadTimeoutHandler(10)));
Timeout for writing data to server
HttpClient httpClient = HttpClient.create() .doOnConnected(conn -> conn .addHandlerLast(new WriteTimeoutHandler(10)));
Get links from link pool timeout needs to rewrite ReactorResourceFactory yourself
private Supplier connectionProviderSupplier = () -> { return ConnectionProvider.fixed("webflux", 500,45000);//Set timeout to 45s};
Using WebClient makes it easy to use Reactor-style asynchronous calls, but you need to know why.
After reading the above, do you know what the internal details are when using WebClient? If you still want to learn more skills or want to know more related content, welcome to pay attention to the industry information channel, thank you for reading!