物联网长连接应采用事件驱动而非多进程模型;NioEventLoopGroup线程数默认设为2×CPU核心数,以平衡I/O等待与事件处理,避免CPU闲置。
因为长连接项目本质是I/O密集型,但“count进程数”设为CPU核心数,通常意味着你误用了进程模型去扛连接,而不是用事件驱动——这个配置本身就有问题,得先分清场景。
别把Netty的NioEventLoopGroup线程数和“count进程数”混为一谈
物联网长连接(如MQTT、CoAP、自定义TCP心跳)几乎全是I/O密集型:线程大部分时间在等网络数据到达,而非计算。这时候用多进程(比如用fork起多个worker进程)是低效的,尤其当连接数上万时,每个进程都带完整内存上下文,开销爆炸。
真正该关注的是:
中
线程数,不是系统级进程数。它的默认值是
,原因很实在:
一个线程在等网络包时会阻塞在
或
,此时CPU空闲
另一个线程正好可以处理已就绪的读写事件,避免CPU闲置
乘以2是经验值,平衡了等待与处理,不是拍脑袋定的
如果你真在用多进程(比如Go的goroutine + fork,或Python的multiprocessing)
那“设为CPU核心数”只在极少数情况下合理:
每个进程内部是单线程+阻塞IO(比如老式PHP-FPM模型),且连接数不高(
你在做CPU密集型预处理(如解密、协议解析)并希望每个进程独占一个物理核
你明确禁用了超线程,且确认每个进程绑定到独立物理核(用
或
)
否则,盲目设成CPU核心数只会导致:
连接数增长时,新连接排队等待accept,延迟飙升
进程间无法共享连接状态,心跳/重连逻辑变复杂
内存占用翻倍(每个进程都要加载TLS证书、协议栈、缓冲区)
真实项目里更常见的错误配置
很多团队看到“CPU核心数”就无脑套用,结果踩坑:
用Java写Netty服务,却把
硬编码成
——在16核机器上只跑4个eventLoop,吞吐直接砍掉60%
用Node.js跑MQTT Broker,没调
,大量
或
阻塞主线程,导致ping响应超时
在MTK安卓主板上启多个Java进程处理4G模块AT指令,结果串口资源被抢占,
频发
关键不在“设多少”,而在“谁在等、等什么、能不能并发处理”。长连接的瓶颈从来不是CPU算力,而是内核socket队列长度、TIME_WAIT回收速度、以及应用层如何批量处理就绪事件——这些比纠结“进程数=核心数”重要得多。
NioEventLoopGroupeventLoop2 * CPU核心数epoll_waitkqueuetasksetsched_setaffinityNioEventLoopGroup(4)Runtime.getRuntime().availableProcessors()UV_THREADPOOL_SIZEfs.readcrypto.pbkdf2IOException: Device or resource busy