明白,你想深入了解 Spring Reactive / Netty 的线程模型 和 CPU 密集任务处理。我们逐条拆解,非常详细。
EventLoopGroup ├── EventLoop-1 (Thread-1) ├── EventLoop-2 (Thread-2) └── EventLoop-3 (Thread-3)
一个 EventLoop 可以服务多个连接。
连接与 EventLoop 是固定绑定的:
当连接建立时,会分配到某个 EventLoop。
该连接的所有 I/O 事件都在这个 EventLoop 线程处理。
这样保证:
事件顺序
无锁处理单连接状态
高 CPU cache 命中
✅ 典型配置:
假设 4 核 CPU:
EventLoopGroup = 4 个 EventLoop(4 个线程)
每个 EventLoop 负责 1000 个连接
EventLoop 内部是单线程循环:
read → decode → handle → encode → write
保证顺序且无需锁
Connection-1 → EventLoop-1 Connection-2 → EventLoop-2 Connection-3 → EventLoop-1 Connection-4 → EventLoop-3
EventLoop 不能阻塞,阻塞会卡住整个 EventLoop,导致 QPS 崩盘。
Spring Reactive 提供了不同类型的 调度器:
Schedulers.boundedElastic()
Schedulers.parallel()
Schedulers.single()
Mono.fromCallable(() -> heavyCompute()) .subscribeOn(Schedulers.parallel()) // 切到线程池 .map(result -> processResult(result));
Mono.fromCallable
Mono.fromCallable(() -> blockingDBCall()) .subscribeOn(Schedulers.boundedElastic()) // 弹性线程池
subscribeOn
publishOn
⚠️ 核心原则:
EventLoop 只做非阻塞 I/O,CPU/阻塞任务切到线程池
boundedElastic()
Go:直接在 goroutine 中阻塞 CPU / I/O 都安全
Spring Reactive:阻塞 EventLoop = 灾难
Go 的优势:
心智负担低
并发几乎无限制
Spring Reactive:
强调“非阻塞 + 调度切换”
错误容易
学习曲线陡峭
✅ 总结一句话
Spring Reactive 的 EventLoop 固定处理多个连接,CPU 密集任务必须切线程池;Go goroutine 可以直接阻塞,runtime 会自动调度线程,无需显式切线程池。
如果你愿意,我可以画一张图,直观对比 EventLoop + Worker Pool vs Go runtime 的 M:N 调度模型,一眼就能看懂两者的本质差异。
你想让我画吗?
Github开源生信云平台 DEMO