跳到正文
Elaine Blog
返回

Reactor 与 Spring WebFlux:背压、线程切换和阻塞边界

Spring 生态与源码

WebFlux 适合端到端非阻塞、并发连接多且单请求大量等待 I/O 的系统。它不会让阻塞 JDBC 自动非阻塞,也不应因为“线程少”被默认选中。

Table of contents

Open Table of contents

运行 Reactor 流水线

ReactorSample下载创建 1 到 5 的 Flux,变换、切换下游执行线程并收集结果:

mvn -Dtest=SpringSourceLabTest#reactorPipelineTransformsValues test

测试在最外层使用 block() 取得结果;WebFlux 请求处理链内部不应 block(),否则可能卡住事件循环。

Mono、Flux 与订阅

Mono<T> 表示 0 或 1 个元素,Flux<T> 表示 0 到多个元素。操作符通常只组装流水线,订阅后数据才流动,因此异常发生位置与组装栈可能不同。

背压让下游通过 demand 告诉上游还需要多少元素。它要求生产者可控制速度;不可暂停的外部事件仍需要有界缓冲、丢弃或拒绝策略。

publishOn 与 subscribeOn

publishOn 影响其后操作符的执行线程,subscribeOn 影响订阅源头。线程切换有队列与上下文成本,不要在每个操作符之间随意切换。

阻塞 SDK 若暂时无法替换,可放到 boundedElastic 并限制并发,但这只是隔离。数据库连接池和远程配额仍是硬上限。

ThreadLocal 不再可靠

响应式链可以跨线程执行,请求 ID、认证和事务上下文应放入 Reactor Context。命令式事务绑定 ThreadLocal,响应式事务使用 ReactiveTransactionManager 和 Reactor Context,二者不能混用。

MVC 还是 WebFlux

阻塞式依赖占主导、团队熟悉同步调试时,MVC 配合虚拟线程可能更简单。大量流式连接、下游已有响应式驱动时再评估 WebFlux。用同一业务负载测量吞吐、P99、内存和排障成本。

Spring 官方说明 WebFlux 是非阻塞框架并支持 Reactive Streams 背压,参阅WebFlux 文档

下一步

阅读AOT、GraalVM Native Image 与 CRaC,比较三种启动优化路线。


分享这篇文章:

上一篇
Spring 6/7 与 Boot 3/4 迁移
下一篇
AOT、GraalVM Native Image 与 CRaC