使用WebClient时,你必须要知道的一些内部细节

本文详细介绍了WebClient的内部细节,包括默认使用全局Reactor-Netty资源,如事件循环线程池和连接管理池。当全局资源不足以应对复杂场景时,可以自定义资源。WebClient默认在IO线程执行回调,对于耗时操作应切换到其他线程。此外,还讨论了连接超时、读取超时和写入超时的配置方法。了解这些细节有助于优化并发性能和避免超时问题。
摘要由CSDN通过智能技术生成

前言

WebClient-Reactor风格的异步调用 我们聊了WebClient的使用,以及线程模型,本文我们来一起看看,使用过程中需要注意的事情。

WebClient的一些内部细节

默认使用全局资源

默认情况下,所有WebClient的实例,公用Reactor.netty.http.HttpResources中包含的全局Reactor -Netty资源,资源这里具体是指事件循环处理线程池(event loop group)和连接管理池(http连接池)。

这是Spring的推荐的模式,因为复用事件循环线程池是并发调优的首选。

全局资源中默认的事件循环处理线程池中包含12个线程。连接池默认支持最大500个连接,并且当达到最大链接后,使用无界队列缓存待获取链接的请求,另外如果超过45000ms还没获取到链接则报超时。

注:由于连接池中链接是不区分域名的,如果有些域名的响应很耗时,则可能一直持有链接不释放,这可能会影响其他域名的请求。

这时,你可以自定义资源,避免使用全局资源:

@Bean
public ReactorResourceFactory resourceFactory() {
    ReactorResourceFactory factory = new ReactorResourceFactory();
    factory.setUseGlobalResources(false); 
    return factory;
}


@Bean
public WebClient webClient() {


    Function<HttpClient, HttpClient> mapper = client -> {
        // Further customizations...
    };


    ClientHttpConnector connector =
            new ReactorClientHttpConnector(resourceFactory(), mapper); 


    return WebClient.builder().clientConnector(connector).build(); 
}

但是这样会导致不能复用事件处理线程池。

默认IO线程执行回调

WebClient默认内部使用Netty实现http客户端调用,这里IO线程其实是netty的IO线程,而netty客户端的IO线程内是不建议做耗时操作的,因为IO线程是用来轮训注册到select上的channel的数据的,如果阻塞了,那么其他channel的读写请求就会得不到及时处理。所以如果consumer内逻辑比较耗时,建议从IO线程切换到其他线程来做。

那么如何切换那?可以使用publishOn把IO线程切换到自定义线程池进行处理:

resp.publishOn(Schedulers.elastic())//切换到Schedulers.elastic()对应的线程池进行处理
        .onErrorMap(throwable -> {
            System.out.println("onErrorMap:" + throwable.getLocalizedMessage());
            return throwable;
        }).subscribe(s -> System.out.println("result:" + Thread.currentThread().getName() + " " + s));

超时相关的配置

  • 与服务端建立链接超时

HttpClient httpClient = HttpClient.create()
        .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);


WebClient webClient = WebClient.builder()
        .clientConnector(new ReactorClientHttpConnector(httpClient))
        .build();
  • 从服务端读取数据超时

HttpClient httpClient = HttpClient.create()
        .doOnConnected(conn -> conn
                .addHandlerLast(new ReadTimeoutHandler(10)));
  • 写数据到服务端超时

HttpClient httpClient = HttpClient.create()
        .doOnConnected(conn -> conn
                .addHandlerLast(new WriteTimeoutHandler(10)));
  • 从链接池获取链接超时 需要自己重写ReactorResourceFactory

private Supplier<ConnectionProvider> connectionProviderSupplier = () -> {
   return ConnectionProvider.fixed("webflux", 500,45000);//设置超时时间为45s
};

总结

使用WebClient可以便捷的使用Reactor风格的异步调用,但是知其然还要知其所以然。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WebClient 使用 Fastjson,您需要将 Fastjson 添加为项目的依赖。可以在项目的 pom.xml 文件添加以下依赖: ```xml <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.78</version> </dependency> ``` 然后,您可以使用 WebClient 发起 HTTP 请求,并使用 Fastjson 来解析响应的 JSON 据。下面是一个示例代码: ```java import com.alibaba.fastjson.JSON; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.web.reactive.function.client.WebClient; public class FastjsonExample { public static void main(String[] args) { WebClient webClient = WebClient.create(); // 发起 GET 请求 webClient.get() .uri("https://api.example.com/data") .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .retrieve() .bodyToMono(String.class) .subscribe(response -> { // 使用 Fastjson 解析 JSON 响应 DataObject dataObject = JSON.parseObject(response, DataObject.class); System.out.println(dataObject); }); } private static class DataObject { // 定义与 JSON 结构对应的据模型 private String name; private int age; // getter 和 setter 方法 // ... } } ``` 上述示例,我们使用 WebClient 发起了一个 GET 请求,并指定接受 JSON 格式的响应。通过调用 `bodyToMono(String.class)` 方法,我们将响应转换为字符串类型。然后,使用 Fastjson 的 `parseObject` 方法将 JSON 字符串解析为据模型对象 `DataObject`。 请注意,示例的 `DataObject` 类需要根据实际 JSON 结构进行定义,以便与 JSON 据正确映射。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值