不存在“go 原生 netpoll 库”,因 runtime/netpoll 是未导出的私有运行时组件;实际可用的是第三方库 github.com/cloudwego/netpoll,它支持空闲检测、et 模式、零拷贝等长连接关键特性。
没有现成的“基于 go 原生 netpoll”的微型长连接框架库开源项目——因为 go 标准库中根本不存在名为 netpoll 的公开导出包。
这是最容易踩的第一个坑:很多人在搜索“Go netpoll 源码”或“Go 原生 netpoll 库”时,实际找到的是 runtime/netpoll(内部未导出包),或是字节跳动开源的第三方库 github.com/cloudwego/netpoll。二者完全不是一回事。
为什么找不到“Go 原生 netpoll 库”
Go 标准库的网络调度底层确实依赖 runtime/netpoll,但它被设计为运行时私有组件:
-
runtime/netpoll不在go.dev文档中公开,go list std也查不到,无法 import - 它的 API 随 Go 版本频繁变更(例如 Go 1.19 重构了 poller 状态机,Go 1.22 调整了 timer 与 netpoll 的耦合方式)
- 所有对外暴露的网络能力都封装在
net、net/http等标准包里,用户不直接调用netpoll
你真正想用的其实是 cloudwego/netpoll
如果你看到示例里用了 netpoll.NewEventLoop、netpoll.CreateListener,那一定是引用了 github.com/cloudwego/netpoll —— 这是一个独立开源、可直接 go get 的高性能网络库,不是 Go 标准库的一部分。
它适合做长连接服务的关键点:
- 内置连接空闲检测(
WithIdleTimeout),避免僵尸连接堆积 - 支持 ET 模式 + 边缘触发读取,适合长连接下持续收包场景
- 事件循环可绑定业务 handler,不强制每个连接起 goroutine,内存更可控
- 零拷贝读写接口(
reader.Next(n)/reader.Release())降低 GC 压力
自己封装微型长连接框架时容易漏掉的点
用 cloudwego/netpoll 快速搭一个长连接服务不难,但真要稳定跑线上,这几个细节必须手动补全:
- 连接建立后必须主动设置
SetReadDeadline或启用WithReadTimeout,否则 TCP Keepalive 默认 2 小时不生效,客户端断网后服务端无法及时感知 -
EventLoop.Serve()是阻塞调用,若需热更新或优雅关闭,得自己包装sync.Once+context.WithCancel控制生命周期 - 长连接通常需要心跳帧,但
cloudwego/netpoll不提供协议解析层,得自己实现粘包/拆包逻辑(比如按固定头长度 + body length 字段解析) - 如果用多
EventLoop(即 Multi-Reactor),连接分发策略(RoundRobinorRandom)会影响 CPU 缓存局部性,高并发下建议压测对比
真正难的从来不是启动一个监听器,而是让百万级长连接在内存、超时、错误传播、goroutine 泄漏这四条线上都不出岔子。











