Ser*_*hko 19 spring spring-webflux
我有一个关于Spring WebClient的问题
在我的应用程序中,我需要执行许多类似的API调用,有时我需要在调用中更改标头(身份验证令牌).所以问题出现了,两种选择会更好:
要为MyService.class的所有传入请求创建一个WebClient,通过使其成为private final字段,如下面的代码:
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();
这里出现了另一个问题:WebClient线程安全吗?(因为服务被许多线程使用)
我想提供最大的性能,并以正确的方式使用它,但我不知道WebClient如何在其中工作,以及它如何使用.
谢谢.
Bri*_*zel 24
这里有两个关键的事情WebClient:
ClientHttpConnector您可以在其上配置WebClientWebClient 是不可改变的考虑到这一点,您应该尝试在ClientHttpConnector整个应用程序中重用相同的内容,因为这将共享连接池 - 这可能是性能最重要的事情.这意味着您应该尝试WebClient从同一个WebClient.create()调用派生所有实例.Spring Boot通过为您创建和配置WebClient.Builder可以在应用程序中的任何位置注入的bean来帮助您.
因为WebClient它是不可变的,所以它是线程安全的.WebClient意味着在被动环境中使用,其中没有任何东西与特定线程相关联(这并不意味着您不能在传统的Servlet应用程序中使用).
如果您想更改请求的方式,有几种方法可以实现:
WebClient baseClient = WebClient.create().baseUrl("https://example.org");
Run Code Online (Sandbox Code Playgroud)
Mono<ClientResponse> response = baseClient.get().uri("/resource")
.header("token", "secret").exchange();
Run Code Online (Sandbox Code Playgroud)
// 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();
Run Code Online (Sandbox Code Playgroud)
rou*_*gou 14
根据我的经验,如果您在无法控制的服务器上调用外部 API,则根本不要使用 WebClient,或者在关闭池机制的情况下使用它。连接池带来的任何性能提升都远远超过了(默认的reactor-netty)库中内置的假设,当远程主机突然终止另一个API调用时,该假设将导致一个API调用出现随机错误。有时,您甚至不知道错误发生在哪里,因为所有调用都是从共享工作线程进行的。
我错误地使用了WebClient,因为文档说它RestTemplate将来会被弃用。事后看来,我会使用常规 HttpClient 或 Apache Commons HttpClient,但如果您像我一样并且已经使用 WebClient 实现,则可以通过创建 WebClient 来关闭池,如下所示:
private WebClient createWebClient(int timeout) {
TcpClient tcpClient = TcpClient.newConnection();
HttpClient httpClient = HttpClient.from(tcpClient)
.tcpConfiguration(client -> client.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, timeout * 1000)
.doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(timeout))));
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
}
Run Code Online (Sandbox Code Playgroud)
创建单独的 WebClient 并不意味着 WebClient 将具有单独的连接池。只需查看代码即可HttpClient.create- 它调用HttpResources.get()获取全局资源。您可以手动提供池设置,但考虑到即使使用默认设置也会发生的错误,我认为不值得冒这个风险。
| 归档时间: |
|
| 查看次数: |
9749 次 |
| 最近记录: |