nng 是 nanomsg 唯一推荐的生产级替代品,完全重写、api 更一致、默认启用重试与心跳;pynng 是唯一活跃 python 绑定,支持 asyncio 与同步接口;req/rep 迁移需严格遵循 send→recv 顺序并显式设超时。

nanomsg 已停更,NNG 是当前唯一推荐的生产级替代
nanomsg 项目自 2017 年起进入维护模式,官方明确不再接受新特性或安全更新;所有新项目应直接选用 nng(Nanomsg Next Generation),它不是简单升级,而是完全重写的现代通信库,API 更一致、线程模型更健壮、默认启用连接重试和心跳机制。
- 旧 nanomsg 的
nn_bind()/nn_connect()在 NNG 中统一为listen()/dial(),语义更清晰,且 dialer 可单独配置重连参数(如reconnect_time_min) - NNG 默认禁用 Nagle 算法,TCP 场景下延迟更低;nanomsg 需手动设
NN_TCPNODELAY才能等效 - nanomsg 的
inproc://在 NNG 中行为更严格:必须先listen()后dial(),否则报nng.EINVAL—— 这是常见启动顺序错误根源
pynng 而非 nnpy:Python 用户该选哪个绑定
nnpy 项目已于 2021 年归档,不再兼容 Python 3.11+,且不支持 NNG 的异步 I/O 和 TLS;pynng 是目前唯一活跃、完整覆盖 NNG 协议族的 Python 绑定,支持 asyncio、trio,也提供同步接口。
- 安装只需
pip install pynng,无需编译 nanomsg/C 依赖(它自带静态链接的 NNG) -
nnpy的Socket(nnpy.AF_SP, nnpy.PUB)写法在pynng中变为Pub0()—— 协议类名即语义,不用记数字常量 - 若你用
asyncio,直接调asend()/arecv();同步场景下send()/recv()会自动阻塞,但注意:未设recv_timeout时可能永久挂起
REQ/REP 模式迁移最容易出错的三个地方
NNG 的 Req0/Rep0 行为比 nanomsg 更严格,尤其在超时和状态机管理上,很多“看似能跑通”的 nanomsg 代码迁过来会静默失败。
- nanomsg 允许连续多次
send()(发多个请求),NNG 的Req0必须严格send()→recv()→send(),否则抛nng.ESTATE -
Rep0端必须先recv()再send(),不能反着来;而 nanomsg 对此容忍度高,容易掩盖逻辑 bug - 超时必须显式设置:
recv_timeout=5000(单位毫秒),否则recv()阻塞无上限 —— 这是服务端卡死最常见原因
跨语言互通时,协议层兼容性比 API 更关键
NNG 和 nanomsg 的 wire protocol 不兼容,但 NNG 向下兼容 nanomsg 的 *socket types*(如 PUB/SUB),只要两端都用标准模式(非 raw)、不启用加密或自定义头,就能直连。
立即学习“Python免费学习笔记(深入)”;
- Go 用
mangos(nanomsg 生态)和 Python 用pynng的Pub0/Sub0可互通;但若 Go 端用了mangos/v3(NNG 兼容版),Python 端就必须用pynng,不能混用nnpy - 消息体必须是裸字节流;JSON 或 Protobuf 需自行序列化,NNG 不做任何编码转换 —— 别指望
send({"a":1})能自动转成字节 - TCP 地址写法要一致:
tcp://127.0.0.1:5555可以,tcp://localhost:5555在某些系统 DNS 解析慢会导致连接超时,建议统一用 IP
真正麻烦的从来不是换库,而是旧代码里那些没显式处理超时、没检查返回值、靠运气跑通的 socket 交互逻辑。NNG 把这些“运气”全拿掉了,换来的不是额外工作量,是上线后少查三次凌晨三点的连接中断告警。










