Nats管理服务器

安装NATS服务器

有许多方法可以安装NATS服务器。

从二进制安装

GitHub版本页面上始终提供最新的官方发行版二进制文件。可以使用以下平台:

  • Linux (x86, x86_64, ARM)
  • Windows (x86, x86_64)
  • macOS

平台特定方法

以下方法可能并非全部安装最新发布的版本

GO

确保设置了Go环境,然后使用go get进行安装。

1
go get github.com/nats-io/nats-server

Docker Hub

Docker Hub上提供了最新的官方Docker镜像。
Windows

在Windows上,可以通过Chocolatey安装NATS服务器:

1
choco install nats-server

macOS

在macOS上,可以通过Homebrew安装NATS服务器:

1
brew install nats-server

测试您的安装

要测试您的安装,您可以调用NATS服务器二进制文件,没有选项,也没有配置文件(没有身份验证,没有群集)。

1
nats-server

当服务器成功启动时,您将看到NATS服务器在TCP端口4222上侦听客户端连接:

1
2
3
[18141] 2016/10/31 13:13:40.732616 [INF] Starting nats-server version 0.9.4
[18141] 2016/10/31 13:13:40.732704 [INF] Listening for client connections on 0.0.0.0:4222
[18141] 2016/10/31 13:13:40.732967 [INF] Server is ready

运行NATS服务器

开箱即用,您可以在没有任何自定义设置的情况下运行NATS服务器。

1
nats-server

启用带监控的NATS服务器(可选)

NATS服务器在端口8222上公开监控接口。

1
nats-server -m 8222

如果在启用监控的情况下运行NATS服务器,则会看到以下消息:

1
2
3
4
[18159] 2016/10/31 13:14:03.055572 [INF] Starting nats-server version 0.9.4
[18159] 2016/10/31 13:14:03.055692 [INF] Starting http monitor on 0.0.0.0:8222
[18159] 2016/10/31 13:14:03.055762 [INF] Listening for client connections on 0.0.0.0:4222
[18159] 2016/10/31 13:14:03.055796 [INF] Server is ready

命令行选项

有两种配置服务器的方法。您可以包含一个或多个命令行参数,如下所述,也可以使用配置文件。
常见选项

  • -h, - help 显示帮助消息
  • -v, - version 显示版本信息

服务器选项

  • -a, –addr HOST 绑定主机IP地址(默认是0.0.0.0)
  • -p, –port PORT 客户端连接NATS服务器使用的端口(默认是4222)
  • -P, –pid FILE 存储PID的文件
  • -m, –http_port PORT 使用HTTP端口作为监听端口
  • -ms, –https_port PORT 使用HTTPS端口作为监听端口
  • -c, –config FILE 指定配置文件
  • -client_advertise HOST:PORT配置INFO消息中返回的HOST和PORT

日志选项

  • -l, –log FILE 指定日志输出的文件
  • -T, –logtime 是否开启日志的时间戳(默认为true)
  • -s, –syslog 启用syslog作为日志方法
  • -r, –remote_syslog 远程日志服务器的地址(默认为udp://localhost:514)
  • -D, –debug 开启调试输出
  • -V, –trace 跟踪原始的协议
  • -DV 调试并跟踪

授权认证选项

  • --user user 连接需要的用户名

  • --pass password 连接需要的密码

  • --auth token 连接所需的令牌

TLS安全选项

  • --help_tls TLS 帮助

  • --tls 启用TLS,不验证客户端(默认为false)

  • --tlscert FILE 服务器证书文件

  • --tlskey FILE 服务器证书私钥

  • --tlsverify 启用TLS,每一个客户端都要认证

  • --tlscacert FILE 客户端证书CA用于认证

群集选项

  • --routes [rurl-1,rurl-2]路线征求和连接
  • --cluster [cluster url]请求路由的群集URL

如果启用了路由,则路由(服务器)连接将侦听端口6222。

1
2
3
4
5
[18159] 2016/10/31 13:14:03.055572 [INF] Starting nats-server version 0.9.4
[18159] 2016/10/31 13:14:03.055692 [INF] Starting http monitor on 0.0.0.0:8222
[18159] 2016/10/31 13:14:03.055707 [INF] Listening for route connections on 0.0.0.0:6222
[18159] 2016/10/31 13:14:03.055762 [INF] Listening for client connections on 0.0.0.0:4222
[18159] 2016/10/31 13:14:03.055796 [INF] Server is ready

NATS服务器身份验证

您可以在NATS服务器上启用身份验证,以便客户端在连接时必须验证其身份。 NATS服务器通过命令行或使用配置文件支持单用户身份验证,并通过配置文件支持多用户身份验证。单用户身份验证是真正的单用户。服务器将接受一组设置好的凭据而不接受其他凭据。

命令行选项

您可以通过在命令行上传递所需的凭据来启用启用了单用户身份验证的NATS服务器。命令行支持以下服务器身份验证选项:

  • --user user连接所需的用户
  • --pass password连接所需的密码
  • --auth令牌连接所需的授权令牌

令牌与用户和密码互斥,因此只能使用其中一个。

例如:

1
nats-server -DV --user foo --pass bar

将允许用户foo使用密码登录。

使用带有授权令牌的命令行:

1
nats-server -DV -auth'S3Cr3T0k3n!'

将允许具有该令牌的客户端连接,而不允许其他客户端。

单用户配置选项

可以在配置文件中配置单用户身份验证:

1
2
3
4
5
authorization {
user: derek
password: T0pS3cr3t
timeout: 1
}

如果服务器是群集的一部分,您还可以为路由连接设置单用户身份验证:

1
2
3
4
5
authorization {
user: derek
password: T0pS3cr3t
timeout: 1
}

这两种配置都设置用户和密码以及连接超时。 auth选项也可以设置为使用令牌而不是用户/密码。

多用户身份验证

多用户身份验证只能在配置文件中设置。用户在具有用户/密码对的列表中定义。

例如,要定义两个用户alice和bob:

1
2
3
4
5
6
authorization {
users = [
{user: alice, password: foo}
{user: bob, password: bar}
]
}

您还可以使用变量来设置用户和密码值。例如,这里将密码声明为名为PASS的变量并分配给Joe。

1
2
3
4
5
6
7
8
authorization {
PASS: abcdefghijklmnopqrstuvwxyz0123456789
users = [
{user: alice, password: foo}
{user: bob, password: bar}
{user: joe, password: $PASS}
]
}

nats-server源代码包含一个可用于加密配置文件密码的工具:

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

这允许您存储散列密码而不是纯文本密码。

客户连接字符串

要作为经过身份验证的客户端连接到服务器,您可以在连接字符串中传入凭据。

例如,用户'foo',密码为'bar':

1
nats://foo:bar@localhost:4222

使用令牌'S3Cr3T0k3n!'

1
nats://foo:bar@localhost:4222

服务器还支持“安全/加密”部分中记录的TLS相互身份验证。开发人员文档中还讨论了其他方法。

群集升级

升级群集的基本策略是围绕服务器将群集配置闲置到客户端和其他服务器的能力。当群集配置更改时,客户端会自动了解新服务器。在断开连接的情况下,除了从其连接设置知道的服务器之外,客户端还具有加入群集的服务器列表。

请注意,由于每个服务器都存储自己的权限和身份验证配置,因此添加到群集的新服务器应提供相同的用户和授权,以防止客户端被拒绝或获得意外权限。

为了描述场景,让我们在键盘上获取一些手指,并完成动作。让我们考虑两个服务器的集群:'A'和'B',以及 - 集群应该是三到五个服务器,但为了描述行为和集群升级过程,两个服务器的集群就足够了。

让我们构建这个集群:

1
nats-server -D -p 4222 -cluster nats://localhost:6222 -routes nats://localhost:6222,nats://localhost:6333

上面的命令启动启用了调试输出的nats-server,在端口4222上侦听客户端,以及在端口6222上接受集群连接。-routes选项指定服务器将尝试连接到其他服务器的nats URL列表。这些URL定义在群集对等方上启用的群集端口。

敏锐的读者会注意到自我路线。 Gnatsd将忽略自我路由,但它为所有服务器提供单一一致的配置。

您将看到服务器已启动,我们注意到它会发出一些警告,因为它无法连接到“localhost:6333”。消息更准确地读取:

1
Error trying to connect to route: dial tcp localhost:6333: connect: connection refused

让我们通过启动第二台服务器来解决这个问题:

1
nats-server -D -p 4333 -cluster nats://localhost:6333 -routes nats://localhost:6222,nats://localhost:6333

第二台服务器在端口4333上启动,其集群端口在6333上。否则与“A”相同。

让我们得到一个客户端,这样我们可以观察它在服务器被移除后在服务器之间移动:

1
nats-sub -s nats://localhost:4222 ">"

Nats-sub是所有NATS客户端都包含的订户样本。 Nats-sub订阅主题并打印出收到的任何消息。您可以在nats-sub [here](https://github.com/nats-io/go-nats/tree/master/examples)的go版本中找到源代码。启动订阅者后,您应该在“A”上看到新客户端连接的消息。

我们有两台服务器和一台客户端。是时候模拟我们的滚动升级了。但等等,在我们升级'A'之前,让我们介绍一个新的服务器'T.'服务'T'将在我们执行升级时加入现有的集群。它的唯一目的是为客户提供一个额外的地方,除了'A'之外,确保我们不会在升级过程之后为所有客户提供服务。客户端将在连接时随机选择服务器,除非提供禁用该功能的特殊选项(通常称为“DontRandomize”或“noRandomize”)。您可以阅读更多关于“避免雷鸣群”的信息。可以说客户端在集群中的所有服务器之间均匀地重新分配。在我们的案例中,'A'的1/2客户将跳转到'B',剩下的一半将转为'T'。

让我们开始我们的临时服务器:

1
nats-server -D -p 4444 -cluster nats://localhost:6444 -routes nats://localhost:6222,nats://localhost:6333

大约一瞬间,'A'上的客户了解加入的新集群成员。在我们的动手教程中,nats-sub现在知道3个可能的服务器,'A'(在我们启动工具时指定)和从群集八卦中学习的'B'和'T'。

我们通过向'A'上的终端发出CTRL + C来调用我们的管理员权限并关闭'A',并观察'B'或'T'报告新客户端已连接。那是我们的nats-sub客户端。

我们执行升级过程,更新“A”的二进制文件,然后重新启动“A”:

1
nats-server -D -p 4222 -cluster nats://localhost:6222 -routes nats://localhost:6222,nats://localhost:6333

我们继续升级'B'。请注意,来自“B”的客户端重新连接到“A”和“T”。我们升级并重新启动'B':

1
nats-server -D -p 4333 -cluster nats://localhost:6333 -routes nats://localhost:6222,nats://localhost:6333

如果我们有更多服务器,我们将继续停止,更新,重新启动旋转,就像我们对'A'和'B'所做的那样。重新启动最后一台服务器之后,我们可以继续关闭'T'''T'上的任何客户端'将重新分配给我们的永久集群成员。

种子服务器

在上面的例子中,我们启动了nats-server指定两个聚类路由。可以允许服务器协议驱动它并减少配置量。例如,您可以按如下方式启动A,B和C:
A - 种子服务器

1
nats-server -D -p 4222 -cluster nats:// localhost:6222

B

1
nats-server -D -p 4333 -cluster nats://localhost:6333 -routes nats://localhost:6222

C

1
nats-server -D -p 4444 -cluster nats://localhost:6444 -routes nats://localhost:6222

一旦它们连接到“种子服务器”,它将了解所有其他服务器并相互连接形成完整网格。

NATS服务器安全性

从版本0.7.0开始,服务器可以使用现代TLS语义进行客户端连接,路由连接和HTTPS监控端口。要在客户端端口上启用TLS,请按如下所示添加TLS配置部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Simple TLS config file

listen: 127.0.0.1:4443

tls {
cert_file: "./configs/certs/server-cert.pem"
key_file: "./configs/certs/server-key.pem"
timeout: 2
}

authorization {
user: derek
password: $2a$11$W2zko751KUvVy59mUTWmpOdWjpEm5qhcCZRd05GjI/sSOT.xtiHyG
timeout: 1
}

注意:如果使用https_port选项启用,则此TLS配置也用于监控端口。

服务器需要证书和私钥。生成自签名证书和中间证书颁发机构超出了此范围,但除了Google搜索之外,此文档也很有帮助:https://docs.docker.com/engine/articles/https/

可以使用命令行参数运行服务器以启用TLS功能。

  • --help_tls TLS 帮助

  • --tls 启用TLS,不验证客户端(默认为false)

  • --tlscert FILE 服务器证书文件

  • --tlskey FILE 服务器证书私钥

  • --tlsverify 启用TLS,每一个客户端都要认证

  • --tlscacert FILE 客户端证书CA用于认证

使用为localhost和127.0.0.1自签名的测试证书的示例。

1
2
3
4
5
6
> ./nats-server --tls --tlscert=./test/configs/certs/server-cert.pem --tlskey=./test/configs/certs/server-key.pem

[2935] 2016/04/26 13:34:30.685413 [INF] Starting nats-server version 0.8.0.beta
[2935] 2016/04/26 13:34:30.685509 [INF] Listening for client connections on 0.0.0.0:4222
[2935] 2016/04/26 13:34:30.685656 [INF] TLS required for client connections
[2935] 2016/04/26 13:34:30.685660 [INF] Server is ready

请注意,日志表明客户端连接将需要使用TLS。如果使用-D或-DV在调试模式下运行服务器,则日志将显示每个连接的客户端的密码套件选择。

1
2
3
[15146] 2015/12/03 12:38:37.733139 [DBG] ::1:63330 - cid:1 - Starting TLS client connection handshake
[15146] 2015/12/03 12:38:37.751948 [DBG] ::1:63330 - cid:1 - TLS handshake complete
[15146] 2015/12/03 12:38:37.751959 [DBG] ::1:63330 - cid:1 - TLS version 1.2, cipher suite TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

TLS密码

服务器需要TLS 1.2版,并设置现代密码套件的首选项,以避免已知的漏洞。使用Go1.5构建时,服务器的默认首选项如下所示。

1
2
3
4
5
6
7
8
9
10
11
func defaultCipherSuites() []uint16 {
return []uint16{
// The SHA384 versions are only in Go1.5+
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
}
}

可选地,如果您的组织需要特定密码或密码列表,则可以使用cipher_suites选项对其进行配置,如下所示:

1
2
3
4
5
6
7
8
9
tls {
cert_file: "./configs/certs/server.pem"
key_file: "./configs/certs/key.pem"
timeout: 2
cipher_suites: [
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
]
}

支持的密码套件列表位于cipherMap变量中。

客户端TLS相互身份验证

可选地,服务器可以要求客户端需要提供证书,并且可以使用CA权限配置服务器以验证客户端证书。只需添加选项验证TLS配置部分,如下所示:

1
2
3
4
5
6
tls {
cert_file: "./configs/certs/server-cert.pem"
key_file: "./configs/certs/server-key.pem"
ca_file: "./configs/certs/ca.pem"
verify: true
}

如果您希望服务器通过命令行强制执行并需要客户端证书,请使用此示例。

1
> ./nats-server --tlsverify --tlscert=./test/configs/certs/server-cert.pem --tlskey=./test/configs/certs/server-key.pem --tlscacert=./test/configs/certs/ca.pem

此选项仅验证客户端的证书是否已由ca_file选项中指定的CA签名。但是,它不会将客户端证书的任何属性映射到用户的身份。

要使TLS相互身份验证将证书属性映射到用户身份,请将选项verify替换为verify_and_map,如下所示:

1
2
3
4
5
6
7
tls {
cert_file: "./configs/certs/server-cert.pem"
key_file: "./configs/certs/server-key.pem"
ca_file: "./configs/certs/ca.pem"
# Require a client certificate and map user id from certificate
verify_and_map: true
}

证书属性有两个选项可以映射到用户名。第一个是证书的主题备用名称(SAN)字段中的电子邮件地址。虽然使用此属性生成证书超出了本文档的范围,但我们将使用OpenSSL查看:

1
2
3
4
5
6
7
8
9
$ openssl x509 -noout -text -in  test/configs/certs/client-id-auth-cert.pem
Certificate:
-------------<truncated>-------------
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:localhost, IP Address:127.0.0.1, email:derek@nats.io
X509v3 Extended Key Usage:
TLS Web Client Authentication
-------------<truncated>-------------

授权此用户的配置如下:

1
2
3
4
5
authorization {
users = [
{user: "derek@nats.io", permissions: { publish: "foo" }}
]
}

注意:如果SAN字段中有多封电子邮件,则此配置仅适用于第一个电子邮件地址。

第二个选项是使用证书主题中的RFC 2253可分辨名称语法,如下所示:

1
2
3
4
5
6
$ openssl x509 -noout -text -in  test/configs/certs/tlsauth/client2.pem
Certificate:
Data:
-------------<truncated>-------------
Subject: OU=CNCF, CN=example.com
-------------<truncated>-------------

授权此用户的配置如下:

1
2
3
4
5
authorization {
users = [
{user: "CN=example.com,OU=CNCF", permissions: { publish: "foo" }}
]
}

群集TLS相互身份验证

设置群集时,群集中的所有服务器(如果使用TLS)都将验证连接端点和服务器响应。因此,双向检查证书。只能为服务器的群集标识配置证书,从而使客户端和服务器证书与群集形成分开。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cluster {
listen: 127.0.0.1:4244

tls {
# Route cert
cert_file: "./configs/certs/srva-cert.pem"
# Private key
key_file: "./configs/certs/srva-key.pem"
# Optional certificate authority verifying connected routes
# Required when we have self-signed CA, etc.
ca_file: "./configs/certs/ca.pem"
}
# Routes are actively solicited and connected to from this server.
# Other servers can connect to us if they supply the correct credentials
# in their routes definitions from above.
routes = [
nats-route://127.0.0.1:4246
]
}

使用bcrypt保护密码

除了TLS功能外,服务器现在还支持使用bcrypt散列密码和身份验证令牌。要利用这一点,只需使用其bcrypt哈希替换配置中的明文密码,服务器将根据需要自动使用bcrypt

nats-server发行版包含一个用于创建bcrypt哈希的实用程序(util / mkpasswd.go)。不带参数运行它将生成新的安全密码以及相关的哈希。这可用于配置中的密码或令牌。

1
2
3
4
5
~/go/src/github.com/nats-io/nats-server/util> go get golang.org/x/crypto/ssh/terminal
~/go/src/github.com/nats-io/nats-server/util> go build mkpasswd.go
~/go/src/github.com/nats-io/nats-server/util> ./mkpasswd
pass: #IclkRPHUpsTmACWzmIGXr
bcrypt hash: $2a$11$3kIDaCxw.Glsl1.u5nKa6eUnNDLV5HV9tIuUp7EHhMt6Nm9myW1aS

如果您已经选择了密码,则可以在命令行上提供-p标志,输入所需的密码,并为其生成bcrypt哈希:

1
2
3
4
~/go/src/github.com/nats-io/nats-server/util> ./mkpasswd -p
Enter Password: *******
Reenter Password: ******
bcrypt hash: $2a$11$3kIDaCxw.Glsl1.u5nKa6eUnNDLV5HV9tIuUp7EHhMt6Nm9myW1aS

将哈希添加到服务器配置文件的授权部分。

1
2
3
4
authorization {
user: derek
password: $2a$11$3kIDaCxw.Glsl1.u5nKa6eUnNDLV5HV9tIuUp7EHhMt6Nm9myW1aS
}

NATS服务器授权

NATS服务器支持基于每个用户使用主题级权限的授权。基于权限的授权可用于多用户身份验证。

每个权限授予都是一个具有两个字段的对象:经过身份验证的用户可以发布到哪些主题,以及经过身份验证的用户可以订阅哪些主题。解析器慷慨解释意图是什么,因此处理数组和单例。主题本身可以包含通配符。权限可以使用变量。

您可以通过在授权配置块内创建符合以下语法的条目来设置权限:

1
2
3
4
5
6
authorization {
PERMISSION_NAME = {
publish = "singleton" or ["array", ...]
subscribe = "singleton" or ["array", ...]
}
}

重要说明NATS授权仅为白名单,这意味着为了不破坏请求/回复模式,您需要使用Alice和Bob为_INBOX。>模式添加上述规则。如果未经授权的客户端发布或尝试订阅尚未列入白名单的主题,则操作将失败并记录在服务器上,并向客户端返回错误消息。

例子

以下是一个示例授权配置,它定义了四个用户,其中三个用户被分配了显式权限。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
authorization {
ADMIN = {
publish = ">"
subscribe = ">"
}
REQUESTOR = {
publish = ["req.foo", "req.bar"]
subscribe = "_INBOX.>"
}
RESPONDER = {
subscribe = ["req.foo", "req.bar"]
publish = "_INBOX.>"
}
DEFAULT_PERMISSIONS = {
publish = "SANDBOX.*"
subscribe = ["PUBLIC.>", "_INBOX.>"]
}
PASS: abcdefghijklmnopqrstuvwxwz0123456789
users = [
{user: joe, password: foo, permissions: $ADMIN}
{user: alice, password: bar, permissions: $REQUESTOR}
{user: bob, password: $PASS, permissions: $RESPONDER}
{user: charlie, password: bar}
]
}

由于Joe是ADMIN,他可以发布/订阅任何主题。我们使用通配符>来匹配任何主题。

Alice是一个请求者,可以在主题req.fooreq.bar上发布请求,并订阅任何响应(_INBOX.>)。

Charlie没有授予权限,因此继承了默认权限集。您可以通过将继承的默认权限分配给授权配置块内的default_permissions条目来设置它们。

Bob是Alice的任何请求的响应者,因此Bob需要能够订阅请求主题并回复Alice的回复主题,这将是一个_INBOX.>

NATS服务器配置

您可以使用服务器配置文件来配置NATS服务器,包括:

  • 客户端侦听端口
  • HTTP监控端口
  • 客户端认证
  • 群集定义
  • 集群路线
  • 日志
  • 最大客户端连接
  • 最大有效载荷

此外,服务器配置语言支持用于自动化的块范围变量。

配置文件格式

服务器配置文件格式是一种灵活的格式,它结合了传统配置格式中的最佳格式以及JSON和YAML等较新的样式。

配置文件格式支持以下语法:

  • Mixed Arrays: [...]
  • Nested Maps: {...}
  • Multiple comment types: # and //
  • Key value assignments using:
    • Equals sign (foo = 2)
    • Colon (foo: 2)
    • Whitespace (foo 2)
  • Maps can be assigned with no key separator
  • Semicolons as value terminators in key/value assignments are optional

通常,配置参数与命令行参数相同。但请注意以下差异:

  • The listen option is host:port for connections, on the server command line it is -a and -p, no hostport is supported.
  • http/https is only a port on the command line, on the config it is host:port (there’s no config flag for the interface for the monitoring)
  • The -cluster flag is used for defining the host:port where routes can be solicited, on the config file this is called ‘listen’ as part property of a ‘cluster’ object.

示例服务器配置文件

以下演示了NATS服务器配置文件的示例。另请参见NATS服务器自述文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
port: 4242      # port to listen for client connections
net: localhost # optional listen interface, default is 0.0.0.0 (all)

http_port: 8222 # HTTP monitoring port

# Authorization for client connections
authorization {
user: derek
# ./util/mkpasswd -p T0pS3cr3t
password: $2a$11$W2zko751KUvVy59mUTWmpOdWjpEm5qhcCZRd05GjI/sSOT.xtiHyG
timeout: 1
}

# Cluster definition
cluster {

listen: localhost:4244 # host/port for inbound route connections

# Authorization for route connections
authorization {
user: route_user
# ./util/mkpasswd -p T0pS3cr3tT00!
password: $2a$11$xH8dkGrty1cBNtZjhPeWJewu/YPbSU.rXJWmS6SFilOBXzmZoMk9m
timeout: 0.5
}

# Routes are actively solicited and connected to from this server.
# Other servers can connect to us if they supply the correct credentials
# in their routes definitions from above.
routes = [
nats-route://user1:pass1@127.0.0.1:4245
nats-route://user2:pass2@127.0.0.1:4246
]
}

# logging options
debug: false
trace: true
logtime: false
log_file: "/tmp/nats-server.log"

# pid file
pid_file: "/tmp/nats-server.pid"

# Some system overides

# max_connections
max_connections: 100

# maximum protocol control line
max_control_line: 512

# maximum payload
max_payload: 65536

# Duration the server can block on a socket write to a client. Exceeding the
# deadline will designate a client as a slow consumer.
write_deadline: "2s"

变量

NATS服务器配置文件格式支持使用块范围的变量,这些变量可用于配置文件中的模板,特别是可以轻松设置权限字段的组值。

变量可以通过前缀$引用,例如$ PASSWORD。 变量可以在配置文件本身或参考环境变量中定义。

例如:

1
2
3
4
5
6
7
8
authorization {
PASS: abcdefghijklmnopqrstuvwxyz0123456789
users = [
{user: alice, password: foo}
{user: bob, password: bar}
{user: joe, password: $PASS}
]
}

构建NATS服务器群集

NATS支持以群集模式运行每个服务器。您可以将服务器集群在一起,以实现高容量邮件系统以及弹性和高可用性。客户端是群集感知的。

请注意,NATS群集服务器的转发限制为一跳。这意味着每个nats-server实例只会将从客户端收到的消息转发到它有路由的紧邻的nats-server实例。从路由接收的消息将仅分发给本地客户端。因此,建议使用全网状集群或完整图表,以使NATS按预期运行,并在整个文档中进行描述。

群集URL

除了用于侦听客户端的端口之外,nats-server还可以侦听“集群”URL(-cluster选项)。然后,其他nats-server服务器可以将该URL添加到其-routes参数以加入群集。这些选项也可以在配置文件中指定,但为简单起见,本概述中仅显示命令行版本。
没有群集运行

1
nats-server -p 4222

运行简单群集

1
2
3
4
5
# Server A on 10.10.0.1
nats-server -p 4222 -cluster nats://10.10.0.1:5222

# Server B on 10.10.0.2
nats-server -p 4222 -cluster nats://10.10.0.2:5222 -routes nats://10.10.0.1:5222
1
2
3
4
5
# Server A on 10.10.0.1
nats-server -p 4222 -cluster nats://10.10.0.1:5222 -routes nats://10.10.0.2:5222

# Server B on 10.10.0.2
nats-server -p 4222 -cluster nats://10.10.0.2:5222 -routes nats://10.10.0.1:5222

连接到群集中任何服务器的客户端将保持连接到群集,即使它最初连接到的服务器已关闭,只要至少保留一个服务器即可。

命令行选项

支持以下群集选项:

  • --routes [rurl-1,rurl-2]路线征求和连接
  • --cluster nats://host:port请求路由的集群URL

当NATS服务器路由到指定的URL时,它会将自己的集群URL通告给路由路由中的所有其他服务器,从而有效地为所有其他服务器创建路由网格。

注意:使用-routes选项时,还必须指定-cluster选项。

也可以使用服务器配置文件配置群集。

三个服务器群集示例

以下示例演示如何在同一主机上运行3个服务器的集群。我们将从种子服务器开始,并使用-D命令行参数来生成调试信息。

1
nats-server -p 4222 -cluster nats://localhost:4248 -D

或者,您可以使用配置文件,我们称之为seed.conf,其内容类似于:

1
2
3
4
5
6
7
8
# Cluster Seed Node

listen: 127.0.0.1:4222
http: 8222

cluster {
listen: 127.0.0.1:4248
}

并像这样启动服务器:

1
nats-server -config ./seed.conf -D

这将产生类似于的输出:

1
2
3
4
[75653] 2016/04/26 15:14:47.339321 [INF] Listening for route connections on 127.0.0.1:4248
[75653] 2016/04/26 15:14:47.340787 [INF] Listening for client connections on 127.0.0.1:4222
[75653] 2016/04/26 15:14:47.340822 [DBG] server id is xZfu3u7usAPWkuThomoGzM
[75653] 2016/04/26 15:14:47.340825 [INF] server is ready

也可以单独指定主机名和端口。至少需要端口。如果您保留主机名,它将绑定到所有接口('0.0.0.0')。

1
2
3
4
cluster {
host: 127.0.0.1
port: 4248
}

现在让我们再启动两台服务器,每台服务器都连接到种子服务器。

1
nats-server -p 5222 -cluster nats://localhost:5248 -routes nats://localhost:4248 -D

当在同一主机上运行时,我们需要为客户端连接选择不同的端口-p,并为用于接受其他路由的端口选择-cluster。请注意,-routes指向种子服务器的-cluster地址(localhost:4248)。

这是生成的日志。了解它如何连接并注册到种子服务器的路由(... GzM)。

1
2
3
4
5
6
7
8
9
[75665] 2016/04/26 15:14:59.970014 [INF] Listening for route connections on localhost:5248
[75665] 2016/04/26 15:14:59.971150 [INF] Listening for client connections on 0.0.0.0:5222
[75665] 2016/04/26 15:14:59.971176 [DBG] server id is 53Yi78q96t52QdyyWLKIyE
[75665] 2016/04/26 15:14:59.971179 [INF] server is ready
[75665] 2016/04/26 15:14:59.971199 [DBG] Trying to connect to route on localhost:4248
[75665] 2016/04/26 15:14:59.971551 [DBG] 127.0.0.1:4248 - rid:1 - Route connection created
[75665] 2016/04/26 15:14:59.971559 [DBG] 127.0.0.1:4248 - rid:1 - Route connect msg sent
[75665] 2016/04/26 15:14:59.971720 [DBG] 127.0.0.1:4248 - rid:1 - Registering remote route "xZfu3u7usAPWkuThomoGzM"
[75665] 2016/04/26 15:14:59.971731 [DBG] 127.0.0.1:4248 - rid:1 - Route sent local subscriptions

从种子的服务器日志中,我们看到路由确实被接受:

1
2
3
[75653] 2016/04/26 15:14:59.971602 [DBG] 127.0.0.1:52679 - rid:1 - Route connection created
[75653] 2016/04/26 15:14:59.971733 [DBG] 127.0.0.1:52679 - rid:1 - Registering remote route "53Yi78q96t52QdyyWLKIyE"
[75653] 2016/04/26 15:14:59.971739 [DBG] 127.0.0.1:52679 - rid:1 - Route sent local subscriptions

最后,让我们启动第三台服务器:

1
nats-server -p 6222 -cluster nats://localhost:6248 -routes nats://localhost:4248 -D

再次注意,我们使用不同的客户端端口和集群地址,但仍指向地址为nats:// localhost:4248的相同种子服务器:

1
2
3
4
5
6
7
8
9
10
11
12
[75764] 2016/04/26 15:19:11.528185 [INF] Listening for route connections on localhost:6248
[75764] 2016/04/26 15:19:11.529787 [INF] Listening for client connections on 0.0.0.0:6222
[75764] 2016/04/26 15:19:11.529829 [DBG] server id is IRepas80TBwJByULX1ulAp
[75764] 2016/04/26 15:19:11.529842 [INF] server is ready
[75764] 2016/04/26 15:19:11.529872 [DBG] Trying to connect to route on localhost:4248
[75764] 2016/04/26 15:19:11.530272 [DBG] 127.0.0.1:4248 - rid:1 - Route connection created
[75764] 2016/04/26 15:19:11.530281 [DBG] 127.0.0.1:4248 - rid:1 - Route connect msg sent
[75764] 2016/04/26 15:19:11.530408 [DBG] 127.0.0.1:4248 - rid:1 - Registering remote route "xZfu3u7usAPWkuThomoGzM"
[75764] 2016/04/26 15:19:11.530414 [DBG] 127.0.0.1:4248 - rid:1 - Route sent local subscriptions
[75764] 2016/04/26 15:19:11.530595 [DBG] 127.0.0.1:52727 - rid:2 - Route connection created
[75764] 2016/04/26 15:19:11.530659 [DBG] 127.0.0.1:52727 - rid:2 - Registering remote route "53Yi78q96t52QdyyWLKIyE"
[75764] 2016/04/26 15:19:11.530664 [DBG] 127.0.0.1:52727 - rid:2 - Route sent local subscriptions

首先,为种子服务器(... GzM)创建一个路由,然后,接受来自... IyE的路由 - 这是第二个服务器的ID。

种子服务器的日志显示它接受了来自第三台服务器的路由:

1
2
3
[75653] 2016/04/26 15:19:11.530308 [DBG] 127.0.0.1:52726 - rid:2 - Route connection created
[75653] 2016/04/26 15:19:11.530384 [DBG] 127.0.0.1:52726 - rid:2 - Registering remote route "IRepas80TBwJByULX1ulAp"
[75653] 2016/04/26 15:19:11.530389 [DBG] 127.0.0.1:52726 - rid:2 - Route sent local subscriptions

并且来自第二台服务器的日志显示它连接到第三台服务器。

1
2
3
4
5
[75665] 2016/04/26 15:19:11.530469 [DBG] Trying to connect to route on 127.0.0.1:6248
[75665] 2016/04/26 15:19:11.530565 [DBG] 127.0.0.1:6248 - rid:2 - Route connection created
[75665] 2016/04/26 15:19:11.530570 [DBG] 127.0.0.1:6248 - rid:2 - Route connect msg sent
[75665] 2016/04/26 15:19:11.530644 [DBG] 127.0.0.1:6248 - rid:2 - Registering remote route "IRepas80TBwJByULX1ulAp"
[75665] 2016/04/26 15:19:11.530650 [DBG] 127.0.0.1:6248 - rid:2 - Route sent local subscriptions

此时,有一个完整的网状NATS服务器集群。
测试群集

现在,以下应该工作:订阅节点A然后发布到节点C.您应该能够毫无问题地接收消息。

1
2
3
4
5
6
7
8
9
10
11
nats-sub -s "nats://192.168.59.103:7222" hello &

nats-pub -s "nats://192.168.59.105:7222" hello world

[#1] Received on [hello] : 'world'

# GNATSD on Node C logs:
[1] 2015/06/23 05:20:31.100032 [TRC] 192.168.59.103:7244 - rid:2 - <<- [MSG hello RSID:8:2 5]

# GNATSD on Node A logs:
[1] 2015/06/23 05:20:31.100600 [TRC] 10.0.2.2:51007 - cid:8 - <<- [MSG hello 2 5]

容器化NATS服务器

NATS服务器作为Docker Hub上的Docker镜像提供,您可以使用Docker守护程序运行。 NATS服务器Docker镜像非常轻巧,大小不到10 MB。

Synadia积极维护和支持NATS服务器Docker镜像。
用法

要使用Docker容器映像,请安装Docker并拉出公共映像:

1
docker pull nats

运行NATS服务器镜像:

1
docker run -d --name nats-main nats

默认情况下,NATS服务器公开多个端口:

  • 4222 is for clients.
  • 8222 is an HTTP management port for information reporting.
  • 6222 is a routing port for clustering.
  • Use -p or -P to customize.

例如:

1
2
3
4
5
6
$ docker run -d --name nats-main nats
[INF] Starting nats-server version 0.6.6
[INF] Starting http monitor on port 8222
[INF] Listening for route connections on 0.0.0.0:6222
[INF] Listening for client connections on 0.0.0.0:4222
[INF] nats-server is ready

要与主机上公开的端口一起运行:

1
docker run -d -p 4222:4222 -p 6222:6222 -p 8222:8222 --name nats-main nats

要运行第二台服务器并将它们聚集在一起:

1
docker run -d --name = nats-2 --link nats-main nats --routes = nats-route:// ruser:T0pS3cr3t @ nats-main:6222

注意由于Docker镜像使用凭据保护路由,我们需要在上面提供它们。从Docker镜像配置中提取

1
2
3
4
5
6
7
# Routes are protected, so need to use them with --routes flag
# e.g. --routes=nats-route://ruser:T0pS3cr3t@otherdockerhost:6222
authorization {
user: ruser
password: T0pS3cr3t
timeout: 2
}

要验证路由是否已连接:

1
2
3
4
5
6
7
8
9
10
11
$ docker run -d --name=nats-2 --link nats-main nats --routes=nats-route://ruser:T0pS3cr3t@nats-main:6222 -DV
[INF] Starting nats-server version 0.6.6
[INF] Starting http monitor on port 8222
[INF] Listening for route connections on :6222
[INF] Listening for client connections on 0.0.0.0:4222
[INF] nats-server is ready
[DBG] Trying to connect to route on nats-main:6222
[DBG] 172.17.0.52:6222 - rid:1 - Route connection created
[DBG] 172.17.0.52:6222 - rid:1 - Route connect msg sent
[DBG] 172.17.0.52:6222 - rid:1 - Registering remote route "ee35d227433a738c729f9422a59667bb"
[DBG] 172.17.0.52:6222 - rid:1 - Route sent local subscriptions

使用Docker进行群集

下面是一些如何使用Docker设置nats-server集群的示例。我们在名为conf的文件夹下放置了3种不同的配置(每个nats-server服务器一个),如下所示:

1
2
3
4
|-- conf
|-- nats-server-A.conf
|-- nats-server-B.conf
|-- nats-server-C.conf

这些文件中的每一个都具有以下内容:(这里我使用ip 192.168.59.103作为示例,所以只需用服务器中的正确ip替换)
示例1:在预先配置的3个不同服务器上设置集群

在此示例中,三个服务器使用了解其他服务器的配置文件启动。
NATS服务器-A

1
2
3
4
5
6
7
8
9
10
11
12
13
# Cluster Server A

port: 7222

cluster {
host: '0.0.0.0'
port: 7244

routes = [
nats-route://192.168.59.103:7246
nats-route://192.168.59.103:7248
]
}

NATS服务器-B

1
2
3
4
5
6
7
8
9
10
11
12
13
# Cluster Server B

port: 8222

cluster {
host: '0.0.0.0'
port: 7246

routes = [
nats-route://192.168.59.103:7244
nats-route://192.168.59.103:7248
]
}

NATS服务器-C

1
2
3
4
5
6
7
8
9
10
11
12
13
# Cluster Server C

port: 9222

cluster {
host: '0.0.0.0'
port: 7248

routes = [
nats-route://192.168.59.103:7244
nats-route://192.168.59.103:7246
]
}

要启动容器,在每台服务器上,您应该能够按如下方式启动nats-server映像:

1
docker run -it -p 0.0.0.0:7222:7222 -p 0.0.0.0:7244:7244 --rm -v $(pwd)/conf/nats-server-A.conf:/tmp/cluster.conf nats -c /tmp/cluster.conf -p 7222 -D -V
1
docker run -it -p 0.0.0.0:8222:8222 -p 0.0.0.0:7246:7246 --rm -v $(pwd)/conf/nats-server-B.conf:/tmp/cluster.conf nats - c /tmp/cluster.conf -p 8222 -D -V
1
docker run -it -p 0.0.0.0:9222:9222 -p 0.0.0.0:7248:7248 --rm -v $(pwd)/conf/nats-server-C.conf:/tmp/cluster.conf nats - c /tmp/cluster.conf -p 9222 -D -V

示例2:逐个设置nats-server集群

在这种情况下:

  • We bring up A and get its ip (nats-route://192.168.59.103:7244)
  • Then create B and then use address of A in its configuration.
  • Get the address of B nats-route://192.168.59.104:7246 and create C and use the addresses of A and B.

首先,我们创建节点A并使用以下配置启动nats-server服务器:

1
2
3
4
5
6
7
8
9
# Cluster Server A

port: 4222

cluster {
host: '0.0.0.0'
port: 7244

}
1
docker run -it -p 0.0.0.0:4222:4222 -p 0.0.0.0:7244:7244 --rm -v $(pwd)/conf/nats-server-A.conf:/tmp/cluster.conf nats -c /tmp/cluster.conf -p 4222 -D -V

然后我们继续创建下一个节点。我们意识到第一个节点的ip:port为192.168.59.103:7244,所以我们将它添加到routes配置中,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
# Cluster Server B

port: 4222

cluster {
host: '0.0.0.0'
port: 7244

routes = [
nats-route://192.168.59.103:7244
]
}

然后启动服务器B:

1
docker run -it -p 0.0.0.0:4222:4222 -p 0.0.0.0:7244:7244 --rm -v $(pwd)/conf/nats-server-B.conf:/tmp/cluster.conf nats -c /tmp/cluster.conf -p 4222 -D -V

最后,我们创建另一个Node C.我们现在知道A和B的路由,以便我们可以将其添加到其配置中:

1
2
3
4
5
6
7
8
9
10
11
12
13
# Cluster Server C

port: 4222

cluster {
host: '0.0.0.0'
port: 7244

routes = [
nats-route://192.168.59.103:7244
nats-route://192.168.59.104:7244
]
}

港口:4222

集群{
主持人:'0.0.0.0'
港口:7244

路线= [
NATS路线://192.168.59.103:7244
NATS路线://192.168.59.104:7244
]
}

然后开始吧:

1
docker run -it -p 0.0.0.0:4222:4222 -p 0.0.0.0:7244:7244 --rm -v $(pwd)/conf/nats-server-C.conf:/tmp/cluster.conf nats -c /tmp/cluster.conf -p 9222 -D -V

测试集群

现在,以下应该工作:订阅节点A然后发布到节点C.您应该能够毫无问题地接收消息。

1
2
3
4
5
6
7
8
9
10
11
nats-sub -s "nats://192.168.59.103:7222" hello &

nats-pub -s "nats://192.168.59.105:7222" hello world

[#1] Received on [hello] : 'world'

# GNATSD on Node C logs:
[1] 2015/06/23 05:20:31.100032 [TRC] 192.168.59.103:7244 - rid:2 - <<- [MSG hello RSID:8:2 5]

# GNATSD on Node A logs:
[1] 2015/06/23 05:20:31.100600 [TRC] 10.0.2.2:51007 - cid:8 - <<- [MSG hello 2 5]

nats-pub -s“nats://192.168.59.105:7222”你好世界

[#1]收到[你好]:'世界'

节点C日志上的#GNATSD:
[1] 2015/06/23 05:20:31.100032 [TRC] 192.168.59.103:7244 - rid:2 - << - [MSG hello RSID:8:2 5]

节点A日志上的#GNATSD:
[1] 2015/06/23 05:20:31.100600 [TRC] 10.0.2.2:51007 - cid:8 - << - [MSG你好2 5]

教程

有关使用NATS服务器Docker镜像的更多说明,请参阅NATS Docker教程

NATS服务器日志记录

NATS服务器提供各种日志记录选项,您可以通过命令行或配置文件设置这些选项。

配置日志记录

命令行选项

支持以下日志记录操作:

  • -l, –log FILE 指定日志输出的文件
  • -T, –logtime 是否开启日志的时间戳(默认为true)
  • -s, –syslog 启用syslog作为日志方法
  • -r, –remote_syslog 远程日志服务器的地址(默认为udp://localhost:514)
  • -D, –debug 开启调试输出
  • -V, –trace 跟踪原始的协议
  • -DV 调试并跟踪

调试和跟踪

-DV标志启用服务器的跟踪和调试。

1
nats-server -DV -m 8222 -user foo -pass bar

日志文件重定向

1
nats-server -DV -m 8222 -l nats.log

时间戳

如果-T false,则日志条目不带时间戳。默认为true。
系统日志

您可以使用UDP配置syslog:

1
nats-server -s udp://localhost:514

或者系统日志:

1
nats-server -r syslog://<hostname>:<port>

例如:

1
syslog://logs.papertrailapp.com:26900

使用配置文件

所有这些设置也可在配置文件中使用。

1
2
3
4
debug:   false
trace: true
logtime: false
log_file: "/tmp/nats-server.log"

使用logrotate记录旋转

NATS服务器不提供管理日志文件的工具,但它确实包含使日志轮换简单的机制。我们可以使用logrotate这个机制;一个简单的标准Linux实用程序,用于旋转大多数发行版上可用的日志,如Debian,Ubuntu,RedHat(CentOS)等。

例如,您可以使用以下命令配置logrotate

1
2
3
4
5
6
7
8
9
10
/path/to/nats-server.log {
daily
rotate 30
compress
missingok
notifempty
postrotate
kill -SIGUSR1 `cat /var/run/nats-server.pid`
endscript
}

第一行指定后续行将应用于的位置。

文件的其余部分指定日志将每天轮换(“每日”选项),并保留30个旧版本(“旋转”选项)。其他选项在logrorate文档中描述。

postrotate”部分告诉NATS服务器在轮换完成后重新加载日志文件。命令kill -SIGUSR1cat / var / run / nats-server.pid不会终止NATS服务器进程,而是向其发送一个信号,使其重新加载其日志文件。这将导致将新请求记录到刷新的日志文件中。

/var/run/nats-server.pid文件是NATS服务器存储主进程的pid的位置。

一些记录笔记

  • 详细模式下的NATS服务器将记录UNSUB消息的接收,但这并不表示订阅已消失,仅表示已收到消息。日志中的DELSUB消息可用于确定何时删除实际的订阅。

监控NATS服务器

为了监视NATS消息传递系统,gnatsd在专用监视端口上提供轻量级HTTP服务器。监视服务器提供多个端点,包括varz,connz,routez和subsz。所有端点都返回一个JSON对象。

NATS监控端点支持JSONP和CORS,可以轻松创建单页面监控Web应用程序。

启用监控

要启用监视服务器,请使用监视标志-m和监视端口启动NATS服务器,或在配置文件中将其打开。

  • -m, - http_port PORT HTTP PORT用于监视
  • -ms, - https_port PORT使用HTTPS PORT进行监控

例:

1
2
3
4
5
$ gnatsd -m 8222
[4528] 2015/08/19 20:09:58.572939 [INF] Starting gnatsd version 0.8.0
[4528] 2015/08/19 20:09:58.573007 [INF] Starting http monitor on port 8222
[4528] 2015/08/19 20:09:58.573071 [INF] Listening for client connections on 0.0.0.0:4222
[4528] 2015/08/19 20:09:58.573090 [INF] gnatsd is ready</td>

要测试,请运行gnatsd -m 8222,然后转到http://localhost:8222/

监控端点

以下部分描述了每个受支持的监控端点:varz,connz,routez和subsz。
/varz

端点http://localhost:8222/varz报告各种常规统计信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
"server_id": "ec933edcd2bd86bcf71d555fc8b4fb2c",
"version": "0.6.6",
"go": "go1.5.0",
"host": "0.0.0.0",
"port": 4222,
"auth_required": false,
"ssl_required": false,
"max_payload": 1048576,
"max_connections": 65536,
"ping_interval": 120000000000,
"ping_max": 2,
"http_port": 8222,
"ssl_timeout": 0.5,
"max_control_line": 1024,
"start": "2015-07-14T13:29:26.426805508-07:00",
"now": "2015-07-14T13:30:59.349179963-07:00",
"uptime": "1m33s",
"mem": 8445952,
"cores": 4,
"cpu": 0,
"connections": 39,
"routes": 0,
"remotes": 0,
"in_msgs": 100000,
"out_msgs": 100000,
"in_bytes": 1600000,
"out_bytes": 1600000,
"slow_consumers": 0
}

/connz

端点http://localhost:8222/connz报告有关当前连接的更多详细信息。它使用分页机制,默认为1024个连接。

您可以通过URL参数(限制和偏移)控制这些。例如:http://localhost:8222/connzlimit=1&offset=1

您还可以使用subs = 1报告基于每个连接的详细订阅信息。例如:http:// localhost:8222/connz?limit=1&offset=1&subs=1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{
"now": "2015-07-14T13:30:59.349179963-07:00",
"num_connections": 2,
"offset": 0,
"limit": 1024,
"connections": [
{
"cid": 571,
"ip": "127.0.0.1",
"port": 61572,
"pending_size": 0,
"in_msgs": 0,
"out_msgs": 0,
"in_bytes": 0,
"out_bytes": 0,
"subscriptions": 1,
"lang": "go",
"version": "1.0.9",
"subscriptions_list": [
"hello.world"
]
},
{
"cid": 574,
"ip": "127.0.0.1",
"port": 61577,
"pending_size": 0,
"in_msgs": 0,
"out_msgs": 0,
"in_bytes": 0,
"out_bytes": 0,
"subscriptions": 1,
"lang": "ruby",
"version": "0.5.0",
"subscriptions_list": [
"hello.world"
]
}
]
}

/routez

端点http://localhost:8222/routez报告有关群集的活动路由的信息。路由预计很低,因此该端点没有分页机制。

routez端点确实支持/ connz端点的subs参数。例如:http://localhost:8222/routez?subs=1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"now": "2015-07-14T13:30:59.349179963-07:00",
"num_routes": 1,
"routes": [
{
"rid": 1,
"remote_id": "de475c0041418afc799bccf0fdd61b47",
"did_solicit": true,
"ip": "127.0.0.1",
"port": 61791,
"pending_size": 0,
"in_msgs": 0,
"out_msgs": 0,
"in_bytes": 0,
"out_bytes": 0,
"subscriptions": 0
}
]
}

/subsz

端点http://localhost:8222/subz报告有关当前订阅和路由数据结构的详细信息。

1
2
3
4
5
6
7
8
9
10
11
{
"num_subscriptions": 3,
"num_cache": 0,
"num_inserts": 572,
"num_removes": 569,
"num_matches": 200000,
"cache_hit_rate": 0.99999,
"max_fanout": 0,
"avg_fanout": 0,
"stats_time": "2015-07-14T12:55:25.564818051-07:00"
}

创建监控应用程序

NATS监控端点支持JSONP和CORS。您可以轻松创建单页Web应用程序以进行监视。为此,您只需将回调查询参数传递给任何端点。

例如:

1
http://localhost:8222/connz?callback=cb

这是一个JQuery示例实现:

1
2
3
$.getJSON('http://localhost:8222/connz?callback=?', function(data) {
console.log(data);
});

跟踪NATS统计信息

nats-top是一种用于监控nats-server服务器的顶级工具。

nats-top工具提供NATS服务器的动态实时视图。 nats-top可以实时显示有关NATS服务器的各种系统摘要信息,例如订阅,待处理字节,消息数等。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
nats-top

nats-server version 0.6.4 (uptime: 31m42s)
Server:
Load: CPU: 0.8% Memory: 5.9M Slow Consumers: 0
In: Msgs: 34.2K Bytes: 3.0M Msgs/Sec: 37.9 Bytes/Sec: 3389.7
Out: Msgs: 68.3K Bytes: 6.0M Msgs/Sec: 75.8 Bytes/Sec: 6779.4

Connections: 4
HOST CID SUBS PENDING MSGS_TO MSGS_FROM BYTES_TO BYTES_FROM LANG VERSION SUBSCRIPTIONS
127.0.0.1:56134 2 5 0 11.6K 11.6K 1.1M 905.1K go 1.1.0 foo, hello
127.0.1.1:56138 3 1 0 34.2K 0 3.0M 0 go 1.1.0 _INBOX.a96f3f6853616154d23d1b5072
127.0.0.1:56144 4 5 0 11.2K 11.1K 873.5K 1.1M go 1.1.0 foo, hello
127.0.0.1:56151 5 8 0 11.4K 11.5K 1014.6K 1.0M go 1.1.0 foo, hello

安装

可以使用go get安装nats-top。例如:

1
go get github.com/nats-io/nats-top

注意:您可能必须以用户sudo身份运行上述命令,具体取决于您的设置。如果你收到一个你无法安装nats-top的错误,因为你的$ GOPATH没有设置,实际上已经设置了,请使用命令sudo -E go get github.com/nats-io/nats-top来安装nats-top 。 -E标志告诉sudo保留当前用户的环境。

用法

安装完成后,可以使用命令nats-top和optional参数运行nats-top。

1
nats-top [-s server] [-m monitor] [-n num_connections] [-d delay_in_secs] [-sort by]

选项

可选参数包括以下内容:

Option Description
-m monitor 监视nats-server的http端口
-n num_connections 限制请求与服务器的连接(默认为1024)
-d delay_in_secs 屏幕刷新间隔(默认为1秒)
-sort by Field用于排序连接

命令

在nats-top视图中,您可以使用以下命令。
选项

使用o

您还可以使用-sort标志在命令行上设置排序选项。例如:nats-top -sort bytes_to。
limit

使用n <limit>命令设置要从服务器请求的连接的样本大小。

您也可以使用-n num_connections标志在命令行上设置它。例如:nats-top -n 1

请注意,如果n <limit>-sort一起使用,则服务器将遵循允许查询的两个选项,例如:查询具有最大订阅数的连接:nats-top -n 1 -sort subs
s,?和q命令

使用s命令切换显示连接订阅。

使用?命令显示带有选项的帮助消息。

使用q命令退出nats-top
教程

有关nats-top的演练,请查看教程

消费者缓慢

为了支持弹性和高可用性,NATS提供了内置机制来自动修剪用于跟踪订阅者的注册侦听器兴趣图,包括缓慢的消费者和懒惰的侦听器。 NATS自动处理缓慢的消费者。如果客户端没有足够快地处理消息,则NATS服务器会将其关闭。为了支持扩展,NATS提供了对客户端连接的自动修剪。如果订户在乒乓间隔内没有响应来自服务器的ping请求,则客户端被切断(断开连接)。客户端需要重新连接逻辑才能与服务器重新连接。

消费者缓慢

在核心NATS中,无法跟上的消费者与许多其他消息系统的处理方式不同:NATS倾向于保护整个系统而不是容纳特定消费者以确保消息传递。

什么是慢消费者?

慢速消费者是无法跟上从NATS服务器传递的消息流的订户。这是分布式系统中的常见情况,因为生成数据通常比处理数据更容易。当消费者无法足够快地处理数据时,背压将应用于系统的其余部分。 NATS有减少这种背压的机制。

NATS识别客户端或服务器中的慢速消费者,通过服务器监控端点中的已注册回调,日志消息和统计信息提供通知。

慢消费者会怎么样?

当在客户端检测到时,通知应用程序并丢弃消息以允许消费者继续并减少潜在的背压。在服务器中检测到时,服务器将断开与慢速消费者的连接以保护自身和消息传递系统的完整性。

客户中发现的消费者缓慢

客户端可以检测到它是本地连接上的慢使用者,并通过使用异步错误回调通知应用程序。最好在客户端本地捕获慢速消费者,而不是让服务器检测到这种情况。此示例演示如何定义和注册将处理缓慢的使用者错误的异步错误处理程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func natsErrHandler(nc *nats.Conn, sub *nats.Subscription, natsErr error) {
fmt.Printf("error: %v\n", natsErr)
if natsErr == nats.ErrSlowConsumer {
pendingMsgs, _, err := sub.Pending()
if err != nil {
fmt.Printf("couldn't get pending messages: %v", err)
return
}
fmt.Printf("Falling behind with %d pending messages on subject %q.\n",
pendingMsgs, sub.Subject)
// Log error, notify operations...
}
// check for other errors
}

// Set the error handler when creating a connection.
nc, err := nats.Connect("nats://localhost:4222",
nats.ErrorHandler(natsErrHandler))

//在创建连接时设置错误处理程序。
nc,err:= nats.Connect(“nats:// localhost:4222”,
nats.ErrorHandler(natsErrHandler))

使用此示例代码和默认设置,缓慢的使用者错误将生成如下输出:

1
2
error: nats: slow consumer, messages dropped
Falling behind with 65536 pending messages on subject "foo".

请注意,如果您使用的是同步订阅者,则Subscription.NextMsg(timeout time.Duration)也将返回错误,指示消费者速度较慢且消息已被删除。

服务器识别的消费者缓慢

当客户端没有足够快地处理消息时,服务器将缓冲出站连接中的消息到客户端。当发生这种情况并且服务器无法足够快地向客户端写入数据时,为了保护自身,它会将订户指定为“慢速消费者”并且可能丢弃关联的连接。

当服务器启动缓慢的使用者错误时,您将在服务器输出中看到以下内容:

1
[54083] 2017/09/28 14:45:18.001357 [INF] ::1:63283 - cid:7 - Slow Consumer Detected

服务器还将记录遇到的慢速消费者错误的数量,可通过slow_consumers字段中的监控varz端点获得。

处理慢消费者

除了使用NATS流媒体或优化您的消费应用程序外,还有一些选项可用:缩放,计量或调整NATS到您的环境。

扩展队列订阅者

如果您不依赖于消息顺序,这是理想的选择。确保您的NATS订阅属于队列组,然后根据需要通过创建更多服务或应用程序实例进行扩展。对于微服务来说,这是一种很好的方法 - 微服务的每个实例都会收到一部分要处理的消息,只需添加更多服务实例即可。无需更改代码,配置更改或停机时间。

创建可以扩展的主题名称空间

您可以通过主题名称空间进一步分发工作,并在设计中进行一些预见。如果您需要保留消息顺序,此方法很有用。一般的想法是发布到一个深度主题命名空间,并使用通配符订阅,同时为将来自己扩展和分发工作留出空间。

举一个简单的例子,如果您有一个服务从位于整个城市的物联网设备接收遥测数据,您可以发布到主题名称空间,如Sensors.North,Sensors.South,Sensors.East和Sensors.West。最初,您将订阅Sensors。>处理一个消费者中的所有内容。随着企业的发展和数据速率超过消费者可以处理的数量,您可以用四个消费应用程序替换单个消费者,以订阅代表较小数据段的每个主题。请注意,您的发布应用程序保持不变。

衡量发布者

不太有利的选择可能是计量发布者。有几种方法可以实现这一点,从简单地减慢发布者速度到定期发布阻止请求/回复以匹配订阅者费率的更复杂方法。

通过配置调整NATS

可以调整NATS服务器以确定在消费者被认为是慢速之前可以缓冲多少数据,并且一些官方支持的客户端允许调整缓冲区大小。减小缓冲区大小可以让您更快地识别缓慢的消费者。除非您正在处理临时的数据突发,否则通常不建议增加缓冲区大小。通常,增加缓冲容量只会推迟缓慢的消费者问题。

服务器配置

NATS服务器具有写入连接的写入期限。当超过此写入截止日期时,客户端被视为具有较慢的消费者。如果您在服务器中遇到缓慢的使用者错误,则可以增加写入期限以缓冲更多数据。

NATS服务器配置文件中的write_deadline配置选项将对此进行调整:

1
write_deadline:2s

当您有数据突发可以容纳时,调整此参数是理想的选择。确保您不仅仅是推迟了一个缓慢的消费者错误。

客户端配置

大多数官方支持的客户端都有一个待处理消息的内部缓冲区,如果本地订阅没有赶上,它将通过异步错误回调通知您的应用程序。在本地接收错误并不一定意味着服务器已将订阅标识为慢速消费者。

可以通过在创建订阅后设置挂起限制来配置此缓冲区:

1
2
3
if err := sub.SetPendingLimits(1024*500, 1024*5000); err != nil {
log.Fatalf("Unable to set pending limits: %v", err)
}

默认订阅者暂挂消息限制为65536,默认订阅者暂挂字节限制为65536 * 1024

如果客户端达到此内部限制,它将丢弃邮件并继续处理新邮件。这与NATS最多一次交付时一致。应用程序可以检测丢失的消息并从此状态恢复。