NATS是由CloudFoundry的架构师Derek开发的一个开源的、轻量级、高性能的,支持发布、订阅机制的分布式消息队列系统。它的核心基于EventMachine开发,代码量不多,可以下载下来慢慢研究。
不同于Java社区的kafka,nats偏于redis式的消息中间件,不不像Kafka式的可以持久化。
NATS原来是使用Ruby编写,可以实现每秒150k消息,后来使用Go语言重写,能够达到每秒8-11百万个消息,整个程序很小只有3M Docker image,它不支持持久化消息,如果你离线,你就不能获得消息。
NATS适合云基础设施的消息通信系统、IoT设备消息通信和微服务架构。
目前已经采用了NATS系统的公司有:爱立信、HTC、百度、西门子、VMware。
NATS 有 3 个产品
NATS服务器与客户端
NATS服务器:用Golang语言开发,发行版包括二进制发布包和Docker镜像。
NATS客户端:包含了多种语言的客户端。
官方提供的客户端
Go client: https://github.com/nats-io/go-nats
Node.js client: https://github.com/nats-io/node-nats
Ruby client: https://github.com/nats-io/ruby-nats
Java client: https://github.com/nats-io/jnats
C client: https://github.com/nats-io/cnats
C# client: https://github.com/nats-io/csnats
Nginx C client:https://github.com/nats-io/nginx-nats
还有社区提供的客户端:
Spring: https://github.com/cloudfoundry-community/java-nats
Lua: https://github.com/DawnAngel/lua-nats
PHP: https://github.com/repejota/phpnats
Python:https://github.com/mcuadros/pynats
Scala: https://github.com/tyagihas/scala_nats/
Haskell:https://github.com/ondrap/nats-queue
查看客户端API技巧
对于Golang客户端API文档,需要这样:
1)用 Go 下载 go版本客户端源码及使用文档
go git https://github.com/nats-io/go-nats.git
2)使用 Go 文档查看器来查看线上文档
godoc -http :8080
3)通过浏览器访问 API 文档
http://localhost:8080/pkg/github.com/nats-io/gnatsd/
NATS的设计原则是:高性能、可伸缩能力、易于使用,基于这些原则,NATS的设计目标包括:
1)高性能(fast)
2)一直可用(dial tone)
3)极度轻量级(small footprint)
4)最多交付一次(fire and forget,消息发送后不管)
5)支持多种消息通信模型和用例场景(flexible)
NATS理想的使用场景有:
1)寻址、发现
2)命令和控制(控制面板)
3)负载均衡
4)多路可伸缩能力
5)定位透明
6)容错
NATS设计哲学认为,高质量的QoS应该在客户端构建,故只建立了请求-应答,不提供:
1)持久化
2)事务处理
3)增强的交付模式
4)企业级队列
从根本上说,NATS 是关于发布和侦听消息的。这两者都在很大程度上依赖于主题。
**什么是主题?**简单来说,主题只是一串字符,它们构成了发布者和订阅者可以用来查找彼此的名称。它有助于将消息范围限定为流或主题。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KhsRYivK-1678191670802)(null)]
为了跨客户端兼容,我们建议使用 ASCII 字符(将来可能会更改)。
推荐字符:a
到 z
,A
到 Z
和0
到9
(名称区分大小写,不能包含空格)。特殊字符:句点。
(用于分隔主题中的标记)和 * 和 >
(*
和>
用作通配符)。保留的使用者名称:按照惯例,以a`$`开头的使用者名称保留供系统使用(例如,以$SYS
或$JS
或$KV
等开头的使用者名称)
.
字符用于创建主题层次结构。例如,世界时钟应用程序可能会定义以下内容以对相关主题进行逻辑分组:
time.us
time.us.east
time.us.east.atlanta
time.eu.east
time.eu.warsaw
第一个通配符是*
,它将匹配单个标记。例如,如果应用程序想要侦听东部时区,他们可以订阅 time.*.east,这将匹配time.us.east
和time.eu.east
。``
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DG3euyWI-1678191670677)(null)]
第二个通配符是>
它将匹配一个或多个标记,并且只能出现在主题的末尾。例如,time.us.>
将匹配time.us.east
和 time.us.east.atlanta,而 time.us.* 将只匹配 time.us.east
,因为它不能匹配多个。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZfhrPWEQ-1678191672332)(null)]
根据您的安全配置,通配符可以通过创建有时称为窃听的内容来用于监视。在最简单的情况下,您可以为>创建订阅者``。此应用程序将接收在 NATS 群集上发送的所有消息(同样,受安全设置的约束)。
通配符*
可以在同一主题中多次出现。这两种类型也可以使用。例如,*.*.east.>
将接收time.us.east.atlanta
。
建议将主题中的最大bit数量保持在最多 16 个bit的合理值。
NATS 为一对多通信实现了发布-订阅消息分发模型。发布者发送有关主题的消息,侦听该主题的任何活动订阅者都会收到该消息。订阅者还可以注册对通配符主题的兴趣,NATS 是一个发布订阅消息传递系统基于主题.侦听某个主题的订阅者会收到有关该主题发布的消息。如果订阅者未主动侦听主题,则不会收到消息。订阅者可以使用通配符标记(如 *
and>
)来匹配单个标记或匹配主题的尾部。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IiqJ55vW-1678191670642)(null)]
消息由以下部分组成:
消息具有最大大小(在服务器配置中使用max_payload
设置)。默认情况下,大小设置为 1 MB,但如果需要,可以增加到 64 MB(但我们建议将最大邮件大小保持在更合理的值,如 8 MB)。
请求-回复是现代分布式系统中的常见模式。发送请求,应用程序要么等待具有特定超时的响应,要么异步接收响应。
一般来说,消息系统是以异步的形式工作,也就是说,publisher 往 subject 上发布一条消息后,并不在意 subscriber 的 reply 是什么。如果 publisher 在意 subscriber 的 reply 是什么的话,那么消息系统就应该以同步的形式工作,在具体实现中,是通过两次发布订阅来完成的:当 publisher 发布消息后,它会订阅一个特定的 subject,当 subscriber 处理完消息后,它会把 reply 发布到这个特定的 subject。当然,整个过程对使用者是透明的。
NATS 使用其核心通信机制(发布和订阅)支持请求-回复模式。使用回复主题在给定主题上发布请求。响应者侦听该主题并将响应发送到回复主题。回复主题称为“收件箱”。这些是动态定向回请求者的唯一主题,无论任何一方位于何处。
多个 NATS 响应程序可以形成动态队列组。因此,无需在组内手动添加或删除订阅者,即可启动或停止分发消息。它是自动完成的。这允许响应者根据需求扩大或缩小规模。
NATS 应用程序“在退出之前耗尽”(在关闭连接之前处理缓冲的消息)。这允许应用程序在不丢弃请求的情况下缩减。
由于 NATS 基于发布-订阅,因此可观测性就像运行另一个应用程序一样简单,该应用程序可以查看请求和响应以测量延迟、监视异常、直接可伸缩性等。
NATS的强大功能甚至允许多个响应,其中第一个响应被利用,系统有效地丢弃额外的响应。这允许复杂的模式具有多个响应器,减少响应延迟和抖动。
无响应者
当请求发送到没有订阅者的主题时,可以方便地立即了解它。对于此用例,NATS 客户端可以选择加入no_responder消息.这需要支持标头的服务器和客户端。启用后,发送到没有订阅者的主题的请求将立即收到没有正文和503
状态的回复。
大多数客户端将通过引发或返回错误来表示这种情况。例如:
m, err := nc.Request("foo", nil, time.Second);
# err == nats.ErrNoResponders
可以发现 request reply 模式已经有了 RPC 的味道。正是因为 NATS 具备了 RPC 的能力,所以在微服务中采用 NATS 后,系统会更清晰。
当订阅者注册自己以接收来自发布者的消息时,消息传递的 1:N 扇出模式可确保发布者发送的任何消息都能到达已注册的所有订阅者。NATS 提供了一个名为“队列”的附加功能,该功能允许订阅者将自己注册为队列的一部分。作为队列一部分的订阅者形成“队列组”。
例如,考虑基于主题名称以 1:N 模式向所有订户传递邮件(甚至对不属于队列组的订户也会发生传递)。如果订阅者基于队列名称注册,它将始终根据主题名称接收其订阅的消息。但是,如果将更多订户添加到同一队列名称,则它们将成为队列组,并且每次队列组收到消息时,只有一个随机选择的队列组订户将使用一条消息。此类分布式队列是 NATS 提供的内置负载平衡功能。
优势
确保应用程序容错
工作负载处理可以纵向扩展或缩减
无需额外配置
队列组由应用程序及其队列订户定义,而不是由服务器配置定义
队列组名称遵循与科目最重要的是,它们区分大小写,不能包含空格。请考虑使用句点分层构建队列组。
.某些服务器功能可以使用通配符匹配在他们身上。
队列订阅者是扩展服务的理想选择(订阅者队列是一个集群构成的消费者,集群分担消费消息,集群可随时拓展和缩减)。纵向扩展就像运行另一个应用程序一样简单,缩减是终止应用程序,并发出耗尽正在进行的请求的信号。这种灵活性和无需任何配置更改使 NATS 成为一种出色的服务通信技术,可以与所有平台技术配合使用。
当向服务(请求/回复)发出请求并且 NATS 服务器知道没有可用的服务(因为队列组中当前没有订阅主题的客户端应用程序)时,服务器将向请求客户端发送“无响应者”协议消息,该消息将中断阻止 API 调用。这允许应用程序立即做出反应。这进一步支持大规模构建响应速度快的系统,即使面对应用程序故障和网络分区也是如此。
跟捷流]还可以通过将保留策略设置为工作队列策略
并利用流作为队列拉动
消费者]轻松实现处理的水平可扩展性(或使用带有订阅者队列组的显式 ACK 推送使用者)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7t1PYeSm-1678191672299)(null)]
连接到全局分布式 NATS 超级群集时,由于如果群集上没有可用于本地处理请求的侦听器,则服务请求消息只会路由到另一个群集(即另一个区域),因此会自动存在服务异地相关性。