You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Web Client如何忽略响应?高并发内存问题求助

Spring WebClient 高并发场景下的“发后即忘”优化与内存问题解决

Spring WebClient完全支持“发后即忘”模式,但你的当前实现和配置存在几个直接导致内存占用过高、请求卡顿的问题,以下是具体分析和优化方案:

一、当前代码与配置的核心问题

  1. 不必要的响应体读取:你使用bodyToFlux(String.class)会将响应体完整读取到内存中,即便后续忽略结果,高并发下也会积累大量内存对象,这是内存占用过高的主要原因。
  2. 订阅线程池过载:直接调用subscribe()会复用Reactor默认线程池,请求量过大时线程池资源耗尽,引发卡顿。
  3. 连接池配置冗余:maxConnections(5000)和pendingAcquireMaxCount(10000)设置过大,过多的连接和等待队列会占用大量内存,同时增加目标服务的负载压力。

二、实现真正的“发后即忘”模式

要做到仅发送请求、完全忽略响应,核心是不读取响应体并快速释放连接,推荐两种实现方式:

方式1:跳过响应体处理

通过exchangeToMono直接释放响应资源,不读取任何内容:

webClient.get()
        .uri(BASE_URL + "/my_endpoint")
        .header("Authorization", "Bearer " + token)
        .exchangeToMono(clientResponse -> {
            // 立即释放响应资源,跳过所有响应体读取
            clientResponse.releaseBody();
            return Mono.empty();
        })
        .subscribeOn(Schedulers.boundedElastic()) // 指定独立线程池处理订阅逻辑
        .onErrorResume(error -> Mono.empty())
        .subscribe();

方式2:简洁的Void类型响应

使用bodyToMono(Void.class)告诉WebClient无需解析响应体:

webClient.get()
        .uri(BASE_URL + "/my_endpoint")
        .header("Authorization", "Bearer " + token)
        .retrieve()
        .bodyToMono(Void.class)
        .subscribeOn(Schedulers.boundedElastic())
        .onErrorResume(error -> Mono.empty())
        .subscribe();

三、优化连接池配置

连接池大小需匹配目标服务的并发处理能力,而非越大越好,推荐配置:

ConnectionProvider connectionProvider = ConnectionProvider.builder("myConnectionPool")
        .maxConnections(200) // 参考目标服务最大并发处理能力设置,一般200-500足够应对3k/s请求
        .pendingAcquireTimeout(Duration.ofSeconds(1)) // 设置连接获取超时,避免请求无限等待堆积
        .maxIdleTime(Duration.ofSeconds(30)) // 闲置连接自动释放,减少内存占用
        .build();

四、额外优化建议

  • Controller异步化:如果你的接口是同步void返回,建议用自定义线程池异步执行请求发送逻辑,避免阻塞Tomcat主线程:
// 自定义线程池(全局初始化一次)
private final Executor customExecutor = Executors.newFixedThreadPool(10);

@GetMapping(value = "my_endpoint")
public void getSomething(String token) {
    CompletableFuture.runAsync(() -> {
        webClient.get()
                .uri(BASE_URL + "/my_endpoint")
                .header("Authorization", "Bearer " + token)
                .exchangeToMono(clientResponse -> {
                    clientResponse.releaseBody();
                    return Mono.empty();
                })
                .onErrorResume(error -> Mono.empty())
                .block();
    }, customExecutor);
}
  • 监控资源状态:用JVM工具(如VisualVM)监控内存占用、线程池状态,用Reactor的Metrics监控连接池的活跃连接数、等待队列长度,根据实际数据调整配置。

内容的提问来源于stack exchange,提问作者Słowik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 20:03:15