Reactor Netty 1.3.8(2026-10-23)给 HttpServer 加了 maxPipelineDepth(int)。Spring Boot 4.1.2 通过 reactor-bom 2025.0.8 已经带上 1.3.8;4.1.1 还是 1.3.7,反射看不到这个方法。把上限调到 1、接口故意拖 1.5 秒时,同连接三条 HTTP/1.1 流水线请求只会回一条,服务端日志出现 maxPipelineDepth exceeded: 1。
许可证 Apache-2.0。仓库 reactor/reactor-netty。发布说明见 v1.3.8。
1.3.8 多了什么
发布说明里和新的流水线深度相关的条目有两条:
HttpServerConfig/HttpServer.maxPipelineDepth(int)(#4380),对接 Netty 4.2.18+HttpServerCodec的同名配置HttpCompressionOptionsSpec也能指定maxPipelineDepth(#4338)
Javadoc 写的是:在等待响应期间,最多允许解码多少个请求。超出时解码侧抛 IllegalStateException。默认值跟 Netty 一致,是 128。
另外 1.3.8 还依赖 Netty 4.2.19.Final,并加了 WebSocket 服务端指标等改动。本文只核 maxPipelineDepth。
Boot 版本差一档
Maven Central 上:
- Spring Boot 4.1.1 → reactor-bom
2025.0.7→ reactor-netty-http 1.3.7 - Spring Boot 4.1.2 → reactor-bom
2025.0.8→ reactor-netty-http 1.3.8
两个进程各自起一个 WebFlux 应用后,启动日志(摘录):
# Boot 4.1.1 / 1.3.7
RN_VERSION_HINT=.../reactor-netty-http-1.3.7.jar!/
HttpServer.maxPipelineDepth_present=false
HttpServer_methods_containing_Pipeline=
# Boot 4.1.2 / 1.3.8
demo.max-pipeline-depth=<default>
RN_VERSION_HINT=.../reactor-netty-http-1.3.8.jar!/
HttpServer.maxPipelineDepth_present=true
fat jar 里也能直接看到工件:4.1.1 打进 reactor-netty-http-1.3.7.jar 和 netty-common-4.2.17.Final.jar;4.1.2 是 1.3.8 和 netty-common-4.2.19.Final.jar。
在 Boot 里怎么接
Boot 4 的类在 org.springframework.boot.reactor.netty 包下。用 WebServerFactoryCustomizer<NettyReactiveWebServerFactory> 调 HttpServer.maxPipelineDepth:
@Bean
WebServerFactoryCustomizer<NettyReactiveWebServerFactory> pipelineDepthCustomizer(
@Value("${demo.max-pipeline-depth:}") String depth) {
return factory -> {
if (depth == null || depth.isBlank()) {
return;
}
int d = Integer.parseInt(depth.trim());
factory.addServerCustomizers(httpServer -> httpServer.maxPipelineDepth(d));
};
}
/ping 故意慢一点,让同连接后续请求在等响应时进入解码队列:
@GetMapping("/ping")
Mono<String> ping() {
int n = hits.incrementAndGet();
return Mono.delay(Duration.ofMillis(delayMs)).then(Mono.just("pong-138#" + n));
}
启动参数示例:
java -jar rn-138-demo-0.0.1.jar --server.port=8138 --demo.ping-delay-ms=1500
java -jar rn-138-demo-0.0.1.jar --server.port=8139 --demo.max-pipeline-depth=1 --demo.ping-delay-ms=1500
同连接三条流水线
客户端在一条 TCP 连接上连续写出三个 GET /ping(HTTP/1.1 keep-alive),不逐条等响应。命令与日志一致:
python3 pipeline_client.py --port 8138 --count 3
python3 pipeline_client.py --port 8139 --count 3
默认深度(8138)三条都回 200(摘录):
# send 3 pipelined GETs to 127.0.0.1:8138/ping
HTTP/1.1 200 OK
...
pong-138#2
HTTP/1.1 200 OK
...
pong-138#3
HTTP/1.1 200 OK
...
pong-138#4
# bytes=267 status_lines=3
maxPipelineDepth=1(8139)只回一条(摘录):
# send 3 pipelined GETs to 127.0.0.1:8139/ping
HTTP/1.1 200 OK
...
pong-138#2
# bytes=89 status_lines=1
对应服务端 WARN(摘录):
An exception has been observed post termination, use DEBUG level to see the full stack: io.netty.handler.codec.DecoderException: java.lang.IllegalStateException: maxPipelineDepth exceeded: 1
Boot 4.1.1 / 1.3.7 在同样延迟下,三条流水线仍然全回 200,也没有这个配置项可调。
怎么理解这个开关
它限制的是「响应还没写完时,编解码器还能继续解多少个请求」。默认 128,一般业务用不到改。只有你明确知道客户端会在同连接上堆流水线,又希望解码侧更早拒绝,才值得把数字调小。调小之后,超出部分不会悄悄丢掉就算了,连接上会看到解码异常;客户端侧往往只收到已经解完并处理完的那几条响应。
还在 Boot 4.1.1 的,升到 4.1.2 就会带上 1.3.8。不想动 Boot 版本时,也可以单独抬 reactor-netty,但要自己核对和 Boot 管理的 Netty 版本是否合拍;4.1.2 已经对齐到 Netty 4.2.19.Final。
一起交流
分享你的思考,让讨论更进一步。