Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Right way to use Spring WebClient in multi-thread environment

I have one question regarding Spring WebClient

In my application I need to do many similar API calls, sometimes I need change headers in the calls (Authentication token). So the question arises, what would be better of the two options:

  1. To create one WebClient for all incoming requests to MyService.class, by making it private final field, like code below:

    private final WebClient webClient = WebClient.builder()         .baseUrl("https://another_host.com/api/get_inf")         .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)         .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)         .build(); 

Here arises another question: is WebClient thread-safe? (because service is used by many threads)

  1. To create new WebClient for each new request incoming to service class.

I want to provide maximum performance, and to use it in right way, but I don't know how WebClient works inside it, and how it expects to be used.

Thank you.

like image 282
Sergey Luchko Avatar asked Mar 04 '18 12:03

Sergey Luchko


People also ask

Is WebClient multithreaded?

Because WebClient is immutable it is thread-safe. WebClient is meant to be used in a reactive environment, where nothing is tied to a particular thread (this doesn't mean you cannot use in a traditional Servlet application).

Can I use WebClient in Spring MVC?

WebClient has been added in Spring 5 ( spring-webflux module) and provides fluent functional style API. Prior to Spring 5, RestTemplate has been the main technique for client-side HTTP accesses, which is part of the Spring MVC project. Since Spring 5 release, WebClient is the recommended approach.

Which is better RestTemplate or WebClient?

Compared to RestTemplate , WebClient has a more functional feel and is fully reactive. Since Spring 5.0, RestTemplate is deprecated. It will probably stay for some more time but will not have major new features added going forward in future releases. So it's not advised to use RestTemplate in new code.

Is WebFlux multithreaded?

What threads should you expect to see on a server running with Spring WebFlux? On a "vanilla" Spring WebFlux server (e.g. no data access, nor other optional dependencies), you can expect one thread for the server, and several others for request processing (typically as many as the number of CPU cores).


1 Answers

Two key things here about WebClient:

  1. Its HTTP resources (connections, caches, etc) are managed by the underlying library, referenced by the ClientHttpConnector that you can configure on the WebClient
  2. WebClient is immutable

With that in mind, you should try to reuse the same ClientHttpConnector across your application, because this will share the connection pool - this is arguably the most important thing for performance. This means you should try to derive all WebClient instances from the same WebClient.create() call. Spring Boot helps you with that by creating and configuring for you a WebClient.Builder bean that you can inject anywhere in your app.

Because WebClient is immutable it is thread-safe. WebClient is meant to be used in a reactive environment, where nothing is tied to a particular thread (this doesn't mean you cannot use in a traditional Servlet application).

If you'd like to change the way requests are made, there are several ways to achieve that:

configure things in the builder phase

WebClient baseClient = WebClient.create().baseUrl("https://example.org"); 

configure things on a per-request basis

Mono<ClientResponse> response = baseClient.get().uri("/resource")                 .header("token", "secret").exchange(); 

create a new client instance out of an existing one

// mutate() will *copy* the builder state and create a new one out of it WebClient authClient = baseClient.mutate()                 .defaultHeaders(headers -> {headers.add("token", "secret");})                 .build(); 
like image 63
Brian Clozel Avatar answered Oct 19 '22 05:10

Brian Clozel