NATS 开发者文档

介绍

使用NATS进行开发是分布式应用程序技术,常见的NATS功能和特定于库的语法的结合。除了使用本书作为指导之外,某些库还包含其API语言熟悉的格式。例如,Go库具有godoc,而Java库具有javadoc。

Library Doc Link
nats.go godoc
nats.java javadoc
nats.net doxygen
nats.rb yard
nats.ts ts-doc

并非所有库都包含此单独的文档,具体取决于语言社区,但是请确保查阅客户端库README文件以了解更多信息。

连接中

NATS系统通常由带有natstls协议的标准URL标识,例如nats://demo.nats.io。NATS系统可以是单个服务器,小型集群或全局超级集群。在所有这些示例中,我们将依赖于 nats.io提供的单个测试服务器,该服务器位于nats://demo.nats.io4222是NATS的默认端口。
NATS还支持通过tls协议使用TLS的安全连接。大多数客户端都支持使用URL协议tls自动检测安全连接。 tls://demo.nats.io:4443上还有一个运行TLS的演示服务器。 对于许多客户端库,该协议要求已成为可选要求,因此您可以使用demo.nats.io:4222作为URL,并让客户端和服务器确定是否需要TLS。
NATS连接有很多选项,从超时到重新连接设置。

连接到默认服务器

一些库还提供了一种特殊的方法来连接到默认 URL,通常是: nats://localhost:4222

nc, err := nats.Connect(nats.DefaultURL)\
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

连接到特定服务器

NATS客户端库可以采用完整的URL nats://demo.nats.io:4222,以指定要连接的特定服务器主机和端口。
库正在删除对显式协议的要求,并且可能允许demo.nats.io:4222或仅允许demo.nats.io。 在后面的示例中,将使用默认端口4222。 请查阅您特定的客户端库的文档,以了解支持哪些URL格式。
例如,要使用URL连接到演示服务器,可以使用:

// If connecting to the default port, the URL can be simplified
// to just the hostname/IP.
// That is, the connect below is equivalent to:
// nats.Connect("nats://demo.nats.io:4222")
nc, err := nats.Connect("demo.nats.io")
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connectioConnection nc = Nats.connect("nats://demo.nats.io:4222");

连接到集群

连接到集群时,需要考虑一些事项。
-为每个集群成员传递URL(半可选)
-连接算法
-重新连接算法(稍后讨论)
-服务器提供的URL
客户端库首次尝试连接时,它将使用提供给连接选项或功能的URL列表。通常以随机顺序检查这些URL,以确保没有每个客户端都连接到同一服务器。使用第一个成功的连接。可以明确禁用随机化。
客户端连接到服务器后,服务器可以提供其他已知服务器的URL列表。这样,客户端可以连接到一台服务器,并且在重新连接期间仍然可以使用其他服务器。
为了确保初始连接,您的代码应包括合理的前线服务器或种子服务器列表。这些服务器可能知道群集的其他成员,并且可能将这些成员告诉客户端。但是您不必配置客户端以在connect方法中传递集群的每个有效成员。
通过提供传递多个连接选项的功能,NATS可以处理计算机宕机或客户端不可用的可能性。通过增加服务器向客户端提供已知服务器列表的功能,作为客户端服务器协议的一部分,群集创建的网格可以在客户端运行时自然地增长和变化。
注意,失败行为取决于库,请查看客户端库的文档以获取有关如果连接失败会发生的情况的信息。

servers := []string{"nats://127.0.0.1:1222", "nats://127.0.0.1:1223", "nats://127.0.0.1:1224"}

nc, err := nats.Connect(strings.Join(servers, ","))
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

连接名称

可以为连接分配一个名称,该名称将出现在某些服务器监视数据中。此名称不是必需的,但 强烈建议您使用 此名称,因为它的友好连接名称将有助于监视,错误报告,调试和测试。

nc, err := nats.Connect("demo.nats.io", nats.Name("API Name Option Example"))
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

设置连接超时

每个库都有自己的语言首选方式来传递连接选项。最常见的选项之一是连接超时。它限制了建立与服务器的连接所花费的时间。如果提供了多个URL,则此超时将分别应用于每个集群成员。要将连接服务器的最长时间设置为10秒:

nc, err := nats.Connect("demo.nats.io", nats.Name("API Options Example"), nats.Timeout(10*time.Second))
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

Ping/Pong协议

客户端和服务器使用简单的PING / PONG协议来检查它们中的任何一个仍然连接到另一个。客户端会定期对服务器执行ping操作,并以pong响应。
NATS 开发者文档_第1张图片

一旦达到可配置的最大有效ping(无单个pons答复),该连接就会失效。这两个值共同定义了连接的超时时间,该超时时间指定了将问题通知客户端的速度。当操作系统没有检测到套接字错误的远程网络分区时,这也将有所帮助。连接关闭后,客户端将尝试重新连接。当它知道其他服务器时,接下来将尝试这些。
在出现通信(例如消息或客户端ping)的情况下,服务器将不会启动PING / PONG交互。
在通信量很大的连接上,客户端通常会发现PINGS之间存在问题,因此默认的PING间隔通常为几分钟。要将时间间隔设置为20s,并将未执行的ping操作限制为5,因此在闲置100s后强制关闭连接:

// Set Ping Interval to 20 seconds
nc, err := nats.Connect("demo.nats.io", nats.Name("API Ping Example"), nats.PingInterval(20*time.Second), nats.MaxPingsOutstanding(5))
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

控制客户端/服务器协议

客户端和服务器之间的协议非常简单,并且依赖于控制线,有时还依赖于主体。控制行包含要发送的操作(如PING或PONG),后跟回车符和换行符CRLF或“ \r\n”。服务器的设置可以限制控制行的最大大小。对于PING和PONG,这没有起作用,但是对于包含主题名称的消息,控制行长度可能很重要。服务器还配置有最大有效负载大小,该大小限制了邮件正文的大小。服务器在连接时将最大有效负载大小发送给客户端,但当前未告知客户端最大控制行大小。

设置最大控制线尺寸

某些客户端将尝试在内部限制控制行的大小,以防止服务器出现错误。这些客户端可能允许也可能不允许您设置使用的大小,但是如果允许,则应将大小设置为与服务器配置相匹配。
例如,将最大控制行大小设置为2k:

//这不适用于NATS Go Client

获取最大有效载荷大小

虽然客户端无法控制最大有效负载大小,但客户端可以为应用程序建立连接后提供一种获取大小的方法。这将允许应用程序根据需要对通过服务器的数据进行分块或限制。

nc, err := nats.Connect("demo.nats.io")
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

mp := nc.MaxPayload()
log.Printf("Maximum payload is %v bytes", mp)

// Do something with the max payload

开启Pedantic模式

NATS服务器提供了一种学究模式,可以对协议进行额外的检查。默认情况下,此设置为关闭,但您可以将其打开:

opts := nats.GetDefaultOptions()
opts.Url = "demo.nats.io"
// Turn on Pedantic
opts.Pedantic = true
nc, err := opts.Connect()
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

打开/关闭详细模式

NATS服务器还提供详细模式。默认情况下,启用详细模式,服务器将使用+ OK或-ERR答复来自客户端的每条消息。大多数客户端会关闭详细模式,这会禁用所有+ OK流量。错误很少受冗长模式的约束,并且客户端库按记录处理错误。要打开可能用于测试的详细模式:

opts := nats.GetDefaultOptions()
opts.Url = "demo.nats.io"
// Turn on Verbose
opts.Verbose = true
nc, err := opts.Connect()
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

关闭回显信息

默认情况下,如果该连接也对发布的主题感兴趣,则NATS连接将回显消息。这意味着,如果某个连接上的发布者将消息发送给主题,则同一连接上的任何订阅者都将收到该消息。客户端可以选择关闭此行为,以便无论兴趣如何,都不会在同一连接上将邮件传递给订户。
NoEcho选项在所有应用程序都订阅和发布同一主题的BUS模式中很有用。通常,发布表示应用程序已经知道的状态更改,因此在应用程序发布更新的情况下,它不需要自己处理更新。
NATS 开发者文档_第2张图片

请记住,每个连接都必须关闭回显,并且它是针对每个连接而不是针对每个应用程序。同样,打开和关闭回显可能会导致应用程序通信协议发生重大变化,因为基于此设置消息将继续流动或停止流动,并且订阅代码将不显示任何原因。

// Turn off echo
nc, err := nats.Connect("demo.nats.io", nats.Name("API NoEcho Example"), nats.NoEcho())
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

自动重新连接

如果由于某种原因断开连接,大多数(如果不是全部)客户端库将重新连接到NATS系统。重新连接逻辑因库而异,因此请查看客户端库的文档。
通常,客户端将尝试通过呼叫 connect 中提供的URL或在较早连接期间由NATS系统提供的URL 重新连接到它所了解的服务器之一。此功能使NATS应用程序和NATS系统本身可以自我修复并重新配置,而无需进行其他配置或干预。该库可能具有多个选项,以帮助控制重新连接行为,通知重新连接状态并通知新服务器。

禁用重新连接

您可以使用连接选项禁用自动重新连接:

// Disable reconnect attempts
nc, err := nats.Connect("demo.nats.io", nats.NoReconnect())
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

设置尝试重新连接的次数

应用程序可以设置每个服务器的最大重新连接尝试次数。这包括提供给客户端连接呼叫的服务器,以及客户端通过另一台服务器发现的服务器。一旦重新连接到服务器失败连续指定次数,它将从连接列表中删除。成功重新连接到服务器后,客户端将重置服务器失败的重新连接尝试次数。如果服务器从连接列表中删除,则可以在连接时重新发现它。这也有效地重置了连接尝试次数。如果客户端用尽了服务器以重新连接,它将关闭连接并引发错误。

// Set max reconnects attempts
nc, err := nats.Connect("demo.nats.io", nats.MaxReconnects(10))
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

避开雷电群

当服务器出现故障时,可能会使用一种名为Thundering Herd的反模式,所有客户端都将尝试立即重新连接,从而造成拒绝服务攻击。为了防止这种情况,大多数NATS客户端库都会随机分配它们尝试连接的服务器。如果仅使用一台服务器,则此设置无效,但是在集群,随机化或混洗的情况下,将确保没有一台服务器首当其冲地进行客户端重新连接尝试。
但是,如果要禁用用于连接和重新连接的随机过程,以便始终以相同的顺序检查服务器,则可以在大多数库中使用连接选项来执行此操作:

servers := []string{"nats://127.0.0.1:1222",
    "nats://127.0.0.1:1223",
    "nats://127.0.0.1:1224",
}

nc, err := nats.Connect(strings.Join(servers, ","), nats.DontRandomize())
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

在重新连接尝试之间暂停

尝试一遍又一遍地连接到同一台服务器没有太大意义。为了防止这种崩溃和浪费的重新连接尝试,尤其是在使用TLS时,库提供了一个等待设置。通常,客户端确保两次尝试重新连接到 同一 服务器之间至少经过一定时间。具体的实现取决于所使用的库。
此设置不仅可以防止浪费客户端资源,而且还可以在其他服务器不可用时缓解群发雷电的情况。

// Set reconnect interval to 10 seconds
nc, err := nats.Connect("demo.nats.io", nats.ReconnectWait(10*time.Second))
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

监听重新连接事件

因为重新连接主要是在幕后,所以许多库都提供了事件侦听器,您可以用来通知重新连接事件。此事件对于发送大量消息的应用程序尤其重要。

// Connection event handlers are invoked asynchronously
// and the state of the connection may have changed when
// the callback is invoked.
nc, err := nats.Connect("demo.nats.io",
    nats.DisconnectErrHandler(func(nc *nats.Conn, err error) {
        // handle disconnect error event
    }),
    nats.ReconnectHandler(func(nc *nats.Conn) {
        // handle reconnect event
    }))
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

在重新连接尝试期间缓冲消息

NATS客户端库尽力避免被遗忘。您正在使用的库中可能包含的功能之一是能够在连接断开时缓冲传出消息。
在短暂的重新连接期间,客户端可以允许应用程序发布消息,由于服务器处于脱机状态,因此消息将被缓存在客户端中。重新连接后,库将发送这些消息。当达到最大重新连接缓冲区时,客户端将不再可以发布消息,并且将返回错误。
请注意,虽然消息似乎已发送到应用程序,但由于从未重建连接,因此可能从未发送过。您的应用程序应使用确认等模式来确保交付。
对于支持此功能的客户端,您可以使用字节,消息或两者来配置此缓冲区的大小。

// Set reconnect buffer size in bytes (5 MB)
nc, err := nats.Connect("demo.nats.io", nats.ReconnectBufSize(5*1024*1024))
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

保护连接

NATS提供了多种形式的安全性,身份验证,授权和隔离。您可以打开身份验证,以限制对NATS系统的访问。帐户允许隔离主题空间和应用程序组。授权可用于限制单个用户访问特定主题以进行发布和订阅操作。TLS可用于加密客户端和NATS系统之间的所有流量。最后,TLS可用于使用客户端证书来验证客户端身份。通过组合所有这些方法,可以保护对系统和所有消息流的访问。
客户端无法控制访问控制,但是客户端确实提供了与系统进行身份验证,绑定到帐户以及需要TLS所需的配置。

使用用户和密码进行身份验证

对于此示例,使用以下命令启动服务器:

> nats-server --user myname --pass password

您可以使用服务器提供的简单工具加密密码,以将密码传递给nats-server:

> go run mkpasswd.go -p
> password: password
> bcrypt hash: $2a$11$1oJy/wZYNTxr9jNwMNwS3eUGhBpHT3On8CL9o7ey89mpgo88VG6ba

并在服务器配置中使用哈希密码。 客户端仍使用纯文本版本。
该代码使用localhost:4222,以便您可以在计算机上启动服务器来试用它们。

用户/密码连接

使用密码登录时,nats-server将采用纯文本密码或加密密码。

// Set a user and plain text password
nc, err := nats.Connect("127.0.0.1", nats.UserInfo("myname", "password"))
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

使用URL中的用户/密码连接

大多数客户端通过在服务器的URL中接受用户名和密码来轻松传递用户名和密码。 此标准格式为:

nats://user:password@server:port

使用这种格式,您可以使用身份验证连接到服务器,就像使用URL连接一样容易:

// Set a user and plain text password
nc, err := nats.Connect("myname:[email protected]")
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

使用令牌进行身份验证

令牌基本上是随机字符串,非常类似于密码,并且在某些情况下可以提供简单的身份验证机制。但是,令牌仅是安全的,因为它们是秘密的,因此其他身份验证方案可以在大型安装中提供更高的安全性。强烈建议使用其他NATS身份验证机制之一。
对于此示例,使用以下命令启动服务器:

> nats-server --auth mytoken

该代码使用localhost:4222,以便您可以在计算机上启动服务器来试用它们。

使用令牌连接

// Set a token
nc, err := nats.Connect("127.0.0.1", nats.Name("API Token Example"), nats.Token("mytoken"))
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

使用URL中的令牌连接

一些客户端库将允许您使用以下形式将令牌作为服务器URL的一部分传递:

nats://token@server:port

同样,一旦构造了此URL,就可以像正常URL一样进行连接。

// Token in URL
nc, err := nats.Connect("mytoken@localhost")
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

使用NKey进行身份验证

NATS服务器的2.0版本引入了新的质询响应身份验证选项。这个质询响应基于一个称为NKeys的包装器。服务器可以通过多种方式使用这些密钥进行身份验证。最简单的方法是为服务器配置一个已知公钥列表,并使客户端通过用其私钥签名来应对挑战。(可打印的私有NKey称为种子)。质询响应通过确保客户端具有私钥来确保安全性,而且还可以保护服务器永远无法访问私钥的私钥!
根据客户端库的不同,处理质询响应可能不仅需要连接选项中的设置。

opt, err := nats.NkeyOptionFromSeed("seed.txt")
if err != nil {
    log.Fatal(err)
}
nc, err := nats.Connect("127.0.0.1", opt)
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

使用凭证文件进行身份验证

NATS服务器的2.0版本引入了基于JSON Web令牌(JWT)的分散式身份验证的思想。客户端使用用户JWT和相应的NKey私钥与该新方案进行交互。为了帮助简化与JWT的连接,客户端库支持凭据文件的概念。该文件包含私钥和JWT,并且可以使用nsc工具生成。内容如下所示,由于包含私钥,因此应该受到保护。此凭证文件未使用,仅用于示例目的。

-----BEGIN NATS USER JWT-----
eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJUVlNNTEtTWkJBN01VWDNYQUxNUVQzTjRISUw1UkZGQU9YNUtaUFhEU0oyWlAzNkVMNVJBIiwiaWF0IjoxNTU4MDQ1NTYyLCJpc3MiOiJBQlZTQk0zVTQ1REdZRVVFQ0tYUVM3QkVOSFdHN0tGUVVEUlRFSEFKQVNPUlBWV0JaNEhPSUtDSCIsIm5hbWUiOiJvbWVnYSIsInN1YiI6IlVEWEIyVk1MWFBBU0FKN1pEVEtZTlE3UU9DRldTR0I0Rk9NWVFRMjVIUVdTQUY3WlFKRUJTUVNXIiwidHlwZSI6InVzZXIiLCJuYXRzIjp7InB1YiI6e30sInN1YiI6e319fQ.6TQ2ilCDb6m2ZDiJuj_D_OePGXFyN3Ap2DEm3ipcU5AhrWrNvneJryWrpgi_yuVWKo1UoD5s8bxlmwypWVGFAA
------END NATS USER JWT------

************************* IMPORTANT *************************
NKEY Seed printed below can be used to sign and prove identity.
NKEYs are sensitive and should be treated as secrets.

-----BEGIN USER NKEY SEED-----
SUAOY5JZ2WJKVR4UO2KJ2P3SW6FZFNWEOIMAXF4WZEUNVQXXUOKGM55CYE
------END USER NKEY SEED------

*************************************************************

给定信用凭证文件,客户端可以身份验证为属于特定帐户的特定用户:

nc, err := nats.Connect("127.0.0.1", nats.UserCredentials("path_to_creds_file"))
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

使用TLS加密连接

虽然身份验证会限制客户端可以连接的身份,但TLS可用于加密客户端/服务器之间的流量并检查服务器的身份。 此外,在带有NATS的TLS的最安全版本中,可以将服务器配置为验证客户端的身份,从而对其进行身份验证。 在TLS模式下启动时,nats服务器将要求所有客户端都使用TLS连接。 此外,如果配置为使用TLS连接,则客户端库将无法连接到没有TLS的服务器。

使用TLS连接并验证客户端身份

使用TLS连接到验证客户端身份的服务器很简单。 客户端必须提供证书和私钥。 NATS客户端将使用这些证书向服务器证明其身份。 为了使客户端能够验证服务器的身份,还提供了CA证书。
Java示例存储库包含此示例的证书和服务器配置。

> nats-server -c /src/main/resources/tls_verify.conf
nc, err := nats.Connect("localhost",
    nats.ClientCert("resources/certs/cert.pem", "resources/certs/key.pem"),
    nats.RootCAs("resources/certs/ca.pem"))
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Do something with the connection

使用TLS协议连接

客户端(例如Go,Java,Javascript,Ruby和Type Script)支持向NATS connect调用提供包含tls协议的URL。 这将打开TLS,而无需进行进一步的代码更改。 但是,在这种情况下,可能存在某种形式的默认设置或环境设置,以允许您的编程语言的TLS库查找证书和受信任的CA。 除非考虑或修改这些设置,否则这种连接方式很可能会失败。

你可能感兴趣的:(消息队列,分布式,队列)