Skip to content

NATS:技术优雅,天花板明显

引言

作为一个正在开发消息队列的人,我对业界的各种产品都保持关注。NATS 是一个让我印象深刻的项目,技术上很优雅,设计理念也很清晰。但研究下来,我发现 NATS 有个明显的问题:天花板太低了。这不是技术不好,而是定位限制了它的发展空间。

这篇文章分享一下我对 NATS 技术架构的理解,以及为什么我认为它的天花板是明显的。这是个人看法,不代表对 NATS 的否定,只是从消息队列从业者的角度做个分析。

NATS 是什么

NATS 是一个开源的消息系统,由 Derek Collison 创建。Derek Collison 是消息系统领域的资深专家,有 25 年以上的经验,曾参与 Cloud Foundry 的开发。NATS 最初在 Apcera 开发,2018 年 Derek 离开后创立了 Synadia 公司,专门围绕 NATS 做商业化。NATS 是 CNCF 的孵化项目,采用 Apache 2.0 许可。

NATS 的核心特点是轻量和高性能。官方宣称单节点可以处理千万级消息每秒,延迟在微秒级。NATS Server 用 Go 语言编写,单个二进制文件,部署极简。协议是文本协议,只有少数几个动词,非常容易理解和实现。

NATS 的定位是"连接技术"(connective technology),用于云、边缘、IoT 设备之间的通信。它支持多种消息模式:pub/sub、request/reply、队列组。从设计理念上,NATS 强调简单、快速、安全,不追求功能的复杂和全面。

公开的用户案例包括 Capital One、Mastercard、Ericsson、GE、Siemens 等公司,主要应用在微服务通信、边缘计算、IoT 数据采集等场景。

NATS 的架构设计

NATS 采用双层架构:Core NATS 和 JetStream。这个设计思路很清晰。

Core NATS 是纯粹的 pub/sub 系统,完全不做持久化。消息发布后存在内存中,有订阅者在线就投递,没有订阅者就丢弃。这种设计让 Core NATS 极其轻量:单节点可以处理千万级消息每秒,延迟在微秒级,内存占用只有几十 MB。这个性能确实很惊人。

Core NATS 提供的是 at-most-once 投递保证,也就是消息可能丢失。这不是缺陷,而是有意的设计选择。通过放弃持久化和投递保证,换取了极致的性能和简单性。对于不需要持久化的场景(实时监控、心跳、临时通知),这个权衡是合理的。

JetStream 是后来加的持久化层,提供消息存储、重放、at-least-once 和 exactly-once 投递保证。JetStream 引入了 Stream 和 Consumer 的概念,使用 Raft 协议做分布式复制。这让 NATS 可以服务需要持久化的场景。

NATS 的 subject-based 寻址也很聪明。消息通过 subject(字符串)寻址,支持通配符订阅。发布者不需要知道订阅者在哪里,服务器自动路由。服务可以动态上下线、迁移、扩缩容,客户端不需要改配置。这种位置透明的设计很适合云原生环境。

部署也极简。单个二进制文件,不依赖外部组件(不需要 ZooKeeper),配置很少。这让 NATS 可以部署在任何地方:云端、边缘、甚至嵌入到应用里。相比 Kafka 的复杂部署,NATS 的门槛低很多。

从技术角度看,NATS 的设计确实优雅。极简主义贯穿始终,每个选择都有明确的理由。性能数据也很漂亮,文档和社区也不错。作为一个技术产品,NATS 做得很好。

我看到的问题

但研究 NATS 的过程中,我发现了一些让我疑惑的地方。

第一个问题是定位。Core NATS 不持久化,这意味着它只能用于"可以丢消息"的场景。实时监控、心跳、临时通知,这些场景确实存在,但占比不大。互联网公司的核心场景——订单、支付、用户行为、业务事件——都不能丢消息,必须持久化。Core NATS 在这些场景完全用不上。

虽然 JetStream 提供了持久化,但这时候问题又来了。如果我需要持久化,为什么不直接用 Kafka?Kafka 的功能更完整、生态更成熟、案例更多。JetStream 来得太晚了,而且在功能和生态上都不如 Kafka。我作为用户,切换到 JetStream 的动力在哪里?

第二个问题是协议。NATS 有自己的协议,不兼容 Kafka 或 AMQP。这意味着迁移成本很高:客户端代码要重写,Kafka Connect 的几百个连接器用不了,监控工具要换,运维经验要重新积累。这个代价太大了。除非 NATS 有压倒性的优势,否则用户不会切换。

第三个问题是市场规模。我在互联网和云计算领域工作多年,很少听到有人提 NATS。讨论消息队列时,大家说的都是 Kafka、RabbitMQ、Pulsar。NATS 几乎不在主流视野里。

从公开的用户案例看,NATS 主要在金融内部通信、工业数据采集、电信信令这些相对边缘的场景。典型的互联网公司(电商、社交、搜索)很少用 NATS。这说明 NATS 服务的是细分市场,而不是主流市场。即使在一些需要极致性能的场景下,主流选择仍然是优化 Kafka 配置或使用 Redpanda,而不是切换到 NATS。

第四个问题是 Go 语言的限制。NATS Server 用 Go 写的,Go 的 GC 在高负载下可能成为瓶颈。从 GitHub issue 看,NATS 确实存在内存管理问题,JetStream 在某些场景下内存占用异常增高。虽然这些可能是特定问题,但也说明 Go 的内存管理不如 Rust 或 C++ 那么可控。对于追求极致性能的消息系统,语言的限制会逐渐显现。

天花板在哪里

综合这些观察,我的判断是:NATS 的天花板由它的定位决定的

NATS 选择的是"轻量实时通信、不需要持久化"这个细分市场。这个市场确实存在,但太小了。消息队列市场本身就不大,NATS 又在这个不大的市场里选了一个更小的细分方向。即使 NATS 在这个细分市场做到 100% 占有率,规模也上不去。

这也解释了为什么 Synadia(NATS 背后的公司)这么多年还是很小的团队。不是他们做得不好,Derek Collison 是业界大牛,技术能力肯定没问题。但选的赛道太窄了,再怎么做也做不大。相比之下,Confluent(Kafka 背后的公司)服务的是主流市场,所以能做到几千人、几十亿美元估值。

NATS 后来加的 JetStream,本质是在承认"纯内存市场太小了"。但这时候已经晚了,Kafka、Pulsar 已经很成熟。而且 JetStream 的功能和 Kafka 比还是有差距,生态更是远远不如。用户如果需要持久化流处理,第一选择还是 Kafka。

协议不兼容进一步限制了 NATS 的推广。生态迁移成本太高,大部分公司不会冒这个险。即使 NATS 在某些方面比 Kafka 好,但"好一点"不足以抵消迁移成本。除非是全新的项目,否则很难选择 NATS。

我的看法

NATS 会继续存在,服务它的细分市场,但我不认为它会有大的突破。市场规模限制了它的发展空间,这不是技术能改变的。

对我来说,NATS 更多是个反面教材。它证明了:定位比技术更重要。技术做得再优雅,选错了市场,也做不大。极简和高性能是有代价的,放弃持久化就限制了应用场景。新协议的生态成本很高,不兼容主流协议就很难推广。

开发 RobustMQ 时,我经常想起 NATS 的例子。它提醒我不要被技术的优雅吸引,走小众路线。消息队列的主流需求是持久化、可靠传递、数据管道,这是 Kafka 的市场,也应该是 RobustMQ 瞄准的方向。

NATS 的架构确实值得学习:subject-based 寻址、位置透明、单二进制部署,这些设计理念很好。但这些要在"持久化 + 功能完整 + 生态兼容"的基础上实现,而不是为了极简而放弃基础能力。

总结

NATS 是一个技术上很优雅但市场上很受限的产品。它的架构设计追求极简和高性能,在技术层面确实做到了。但定位选择限制了它的发展空间。

轻量实时通信是个细分场景,市场太小。新协议导致生态隔离,迁移成本高。Go 语言带来了性能限制。这些因素共同决定了 NATS 的天花板。

NATS 会有它的生态位,服务特定的用户群体,但不会成为主流。这不是执行问题,而是战略问题。技术做得再好,选错了市场,天花板就在那里。

作为一个消息队列从业者,我很欣赏 NATS 的技术设计,但不会选择它的市场路线。基础设施软件的价值不只在技术优雅,更在于解决主流需求、建立完整生态、服务足够大的市场。这是 NATS 给我的最大启示。