并行执行Mono未出现速度提升,请问代码写法是否存在错误?
并行请求WebClient无提速问题解决方案
核心原因
subscribeOn(Schedulers.parallel())对WebClient请求完全不生效:WebClient是基于Netty实现的非阻塞HTTP客户端,所有IO操作默认绑定Netty的EventLoop调度器,subscribeOn仅对未指定调度器的源Publisher生效,不会改变WebClient本身的执行线程,所以加不加这行不会影响执行效率。- 连接池并发限制是核心瓶颈:WebClient底层默认的Reactor Netty连接池,对同一个域名的最大并发连接数默认仅为2,是遵循HTTP/1.1旧规范的默认配置,并发发起多个请求时大部分请求会排队等待连接释放,最终耗时接近串行请求的累加值。
解决步骤
- 移除
getUserInfo方法中无效的subscribeOn(Schedulers.parallel())代码,并行线程池是为CPU密集型任务设计的,用于IO密集型的HTTP请求只会造成不必要的线程切换开销。 - 自定义WebClient的连接池配置,调大最大并发连接数,示例代码如下:
import io.netty.channel.ChannelOption import io.netty.handler.timeout.ReadTimeoutHandler import io.netty.handler.timeout.WriteTimeoutHandler import org.springframework.http.client.reactive.ReactorClientHttpConnector import org.springframework.web.reactive.function.client.WebClient import reactor.netty.http.client.HttpClient import reactor.netty.resources.ConnectionProvider import java.time.Duration import java.util.concurrent.TimeUnit // 自定义连接池配置 val customConnectionProvider = ConnectionProvider.builder("custom-http-pool") .maxConnections(100) // 根据实际并发需求调整,默认值为2 .pendingAcquireMaxCount(200) // 等待连接的最大排队请求数 .build() val httpClient = HttpClient.create(customConnectionProvider) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000) .responseTimeout(Duration.ofSeconds(5)) .doOnConnected { conn -> conn.addHandlerLast(ReadTimeoutHandler(5)) .addHandlerLast(WriteTimeoutHandler(5)) } // 用自定义配置初始化WebClient val webClient = WebClient.builder() .clientConnector(ReactorClientHttpConnector(httpClient)) .build()
- 原有
Mono.zip的并发逻辑不需要修改,调整完连接池配置后,多个请求会真正并行执行,整体耗时会接近单个请求的耗时。
额外说明
如果你的服务端接口本身有调用频率限制,也可能导致并行请求被限流排队,这种情况需要结合服务端的限流规则调整并发数。
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

