Skip to content

监控与可观测性 ​

目录 ​

  1. 监控端点概览
  2. /varz — 服务器基础信息
  3. /routez — 集群路由
  4. /connz — 客户端连接
  5. /subsz — 订阅统计
  6. /jsz — JetStream 状态
  7. /jsz?streams=1 — Stream 列表
  8. /jsz?consumers=1 — Consumer 列表
  9. /healthz — 健康检查
  10. /leafz — Leaf Node 连接
  11. /gatewayz — Gateway 连接
  12. /accountz — 账号信息
  13. /statz — 统计信息
  14. 常用运维命令集合
  15. 告警指标建议

1. 监控端点概览 ​

NATS Server 内置 HTTP 监控端口(默认 8222),无需额外安装即可使用。所有端点返回 JSON 格式。

bash
# 启动 NATS Server 时开启监控端口
nats-server -m 8222

# 或在配置文件中
# nats-server.conf:
# monitor_port: 8222
端点说明典型用途
/varz服务器基础指标通用性能监控
/routez集群路由状态集群健康检查
/connz客户端连接列表连接问题排查
/subsz订阅统计Subject 分布分析
/jszJetStream 总览JetStream 健康监控
/healthz健康检查K8s 探针
/leafzLeaf Node 连接Leaf Node 管理
/gatewayzGateway 连接多集群监控
/accountz账号信息多租户管理
/statz服务器统计性能趋势

2. /varz — 服务器基础信息 ​

URL: GET http://nats-server:8222/varz

说明: 返回 NATS Server 的核心运行指标,是最常用的监控端点,涵盖连接数、消息吞吐、内存、CPU 等关键信息。

关键字段解释 ​

字段类型说明
server_idstringServer 的唯一标识(启动时生成)
server_namestring配置的 Server 名称(集群节点名)
versionstringNATS Server 版本号
gostring编译使用的 Go 版本
hoststring监听地址
portint客户端连接端口
uptimestring运行时长(可读格式,如 "2d3h")
memint当前内存使用字节数
coresintCPU 核心数
max_connectionsint最大允许连接数
connectionsint当前活跃连接数
total_connectionsint历史累计连接总数
slow_consumersint慢消费者数量(消息积压的连接数)
subscriptionsint当前订阅总数
messages_inint累计接收消息数
messages_outint累计发送消息数
bytes_inint累计接收字节数
bytes_outint累计发送字节数
in_msgsint实时指标:当前统计周期内接收消息数
out_msgsint实时指标:当前统计周期内发送消息数
max_payloadint单条消息最大允许字节数
clusterobject集群信息(节点名、集群名等)
jetstreamobjectJetStream 启用状态和基础配置

示例响应(部分) ​

json
{
  "server_id": "NBQXXXABCDEF123456",
  "server_name": "nats-node-1",
  "version": "2.10.14",
  "proto": 1,
  "go": "go1.21.5",
  "host": "0.0.0.0",
  "port": 4222,
  "max_connections": 65536,
  "ping_interval": 120000000000,
  "ping_max": 2,
  "http_host": "0.0.0.0",
  "http_port": 8222,
  "max_payload": 1048576,
  "jetstream": {
    "config": {
      "max_memory": 4294967296,
      "max_storage": 107374182400,
      "store_dir": "/data/nats/jetstream"
    },
    "stats": {
      "memory": 1048576,
      "storage": 536870912,
      "reserved_memory": 0,
      "reserved_storage": 0,
      "accounts": 1,
      "ha_assets": 6,
      "api": {
        "total": 5678,
        "errors": 2
      }
    }
  },
  "connections": 42,
  "total_connections": 1024,
  "routes": 2,
  "remotes": 2,
  "leafnodes": 0,
  "in_msgs": 12345678,
  "out_msgs": 12345678,
  "in_bytes": 1234567890,
  "out_bytes": 1234567890,
  "slow_consumers": 0,
  "subscriptions": 256,
  "http_req_stats": {
    "/varz": 100,
    "/jsz": 50
  },
  "mem": 52428800,
  "cores": 4,
  "max_procs": 4,
  "now": "2024-01-15T10:30:00.000Z",
  "uptime": "2d3h14m22s",
  "start": "2024-01-13T07:15:38.000Z"
}

使用场景 ​

bash
# 快速查看服务器健康概览
curl -s http://nats:8222/varz | jq '{
  version,
  uptime,
  connections,
  slow_consumers,
  messages_in,
  mem_mb: (.mem / 1048576 | floor)
}'

# 监控消息吞吐趋势(通过对比两次采集的 in_msgs 差值计算 QPS)
# 推荐交给 Prometheus exporter 处理

3. /routez — 集群路由 ​

URL: GET http://nats-server:8222/routez

说明: 返回当前节点与其他集群成员之间的路由连接信息,用于验证集群拓扑和诊断节点间连接问题。

关键字段解释 ​

字段类型说明
num_routesint当前建立的路由连接数(正常值 = 集群节点数 - 1)
routesarray每个路由连接的详情
routes[].ridint路由 ID(内部标识)
routes[].remote_idstring对端节点的 Server ID
routes[].remote_namestring对端节点的配置名称
routes[].did_solicitbool是否是本节点主动发起的连接
routes[].is_configuredbool是否在配置文件中显式配置的路由
routes[].ipstring对端 IP 地址
routes[].portint对端路由端口
routes[].startstring路由建立时间
routes[].last_activitystring最后通信时间
routes[].rttstring网络往返时延(Round-Trip Time),如 "1.2ms"
routes[].uptimestring路由连接已持续时长
routes[].idlestring空闲时长(上次通信到现在)
routes[].in_msgsint从该路由收到的消息数
routes[].out_msgsint向该路由发送的消息数
routes[].subscriptionsint通过此路由订阅的 Subject 数量

示例响应(部分) ​

json
{
  "server_id": "NBQXXX-NODE-1",
  "now": "2024-01-15T10:30:00Z",
  "num_routes": 2,
  "routes": [
    {
      "rid": 1,
      "remote_id": "NBQXXX-NODE-2",
      "remote_name": "nats-node-2",
      "did_solicit": true,
      "is_configured": true,
      "ip": "10.0.0.2",
      "port": 6222,
      "start": "2024-01-13T07:15:40Z",
      "last_activity": "2024-01-15T10:29:58Z",
      "rtt": "0.8ms",
      "uptime": "2d3h14m20s",
      "idle": "2s",
      "in_msgs": 5000000,
      "out_msgs": 5000000,
      "in_bytes": 500000000,
      "out_bytes": 500000000,
      "subscriptions": 128
    },
    {
      "rid": 2,
      "remote_id": "NBQXXX-NODE-3",
      "remote_name": "nats-node-3",
      "did_solicit": true,
      "is_configured": true,
      "ip": "10.0.0.3",
      "port": 6222,
      "rtt": "1.1ms",
      "uptime": "2d3h14m20s",
      "idle": "1s",
      "in_msgs": 4900000,
      "out_msgs": 4900000
    }
  ]
}

使用场景 ​

bash
# 检查集群所有路由是否已建立(3节点集群应显示 num_routes=2)
curl -s http://nats:8222/routez | jq '{
  num_routes,
  routes: [.routes[] | {name: .remote_name, rtt, uptime, idle}]
}'

# 检查节点间 RTT 是否异常(>10ms 表示网络问题)
curl -s http://nats:8222/routez | jq '.routes[] | {name: .remote_name, rtt}'

4. /connz — 客户端连接 ​

URL: GET http://nats-server:8222/connz

参数:

  • ?limit=N — 返回最多 N 个连接(默认 1024)
  • ?offset=N — 分页偏移量
  • ?sort=subs|msgs_from|msgs_to|bytes_from|bytes_to|idle|uptime|start — 排序字段
  • ?state=open|closed|all — 过滤连接状态
  • ?cid=N — 查询指定连接 ID
  • ?user=NAME — 按用户名过滤
  • ?name=PATTERN — 按连接名称过滤(支持通配符)
  • ?subs=1 — 包含每个连接的订阅列表

说明: 列出所有客户端连接的详细信息,用于排查连接泄漏、慢消费者和高流量客户端。

关键字段解释 ​

字段说明
num_connections当前活跃连接总数
connections[].cid连接 ID(本次连接的唯一编号)
connections[].name客户端连接名称(nats.Name() 设置的值)
connections[].ip客户端 IP
connections[].port客户端端口
connections[].start连接建立时间
connections[].uptime连接已持续时长
connections[].idle空闲时长
connections[].lang客户端语言(go、python、java 等)
connections[].version客户端库版本
connections[].subscriptions该连接的订阅数量
connections[].in_msgs该连接收到的消息数
connections[].out_msgs该连接发送的消息数
connections[].pending_bytes待发送给此客户端的积压字节数(> 0 表示慢消费者)

示例响应(部分) ​

json
{
  "server_id": "NBQXXX-NODE-1",
  "now": "2024-01-15T10:30:00Z",
  "num_connections": 42,
  "connections": [
    {
      "cid": 101,
      "name": "order-service-prod-1",
      "lang": "go",
      "version": "1.36.0",
      "ip": "10.0.1.100",
      "port": 54321,
      "start": "2024-01-15T08:00:00Z",
      "uptime": "2h30m",
      "idle": "100ms",
      "in_msgs": 100000,
      "out_msgs": 50000,
      "in_bytes": 10485760,
      "out_bytes": 5242880,
      "subscriptions": 3,
      "pending_bytes": 0,
      "rtt": "0.5ms"
    },
    {
      "cid": 102,
      "name": "slow-consumer-worker",
      "lang": "python",
      "version": "2.3.0",
      "ip": "10.0.1.200",
      "pending_bytes": 5242880,
      "subscriptions": 1
    }
  ]
}

使用场景 ​

bash
# 查找慢消费者(pending_bytes > 0)
curl -s "http://nats:8222/connz?limit=100" | \
  jq '.connections[] | select(.pending_bytes > 0) | {name, ip, pending_bytes}'

# 按消息量排序,找到最活跃的连接
curl -s "http://nats:8222/connz?sort=msgs_to&limit=10" | \
  jq '.connections[:5] | .[] | {name, lang, in_msgs, out_msgs}'

# 查找特定服务的连接
curl -s "http://nats:8222/connz?name=order-service*" | \
  jq '.connections[] | {cid, name, uptime, subscriptions}'

# 查找空闲超过 1 小时的可疑连接(可能是连接泄漏)
curl -s "http://nats:8222/connz" | \
  jq '.connections[] | select(.idle | test("^[1-9][0-9]*h")) | {name, ip, idle}'

5. /subsz — 订阅统计 ​

URL: GET http://nats-server:8222/subsz

参数:

  • ?subs=1 — 包含详细的订阅列表
  • ?offset=N — 分页偏移量
  • ?limit=N — 返回条数限制
  • ?test=SUBJECT — 测试指定 Subject 匹配到哪些订阅

说明: 提供当前所有订阅的统计信息,用于分析 Subject 路由分布和发现孤立订阅。

关键字段解释 ​

字段说明
num_subscriptions本节点当前订阅总数
num_cache路由缓存中的 Subject 数量
num_inserts历史订阅插入次数
num_removes历史订阅移除次数
num_matches路由匹配总次数(消息分发性能参考)
cache_hit_rate路由缓存命中率(越高越好,> 90% 正常)
max_fanout历史最大 Fanout 值(一条消息分发到的最多订阅数)
avg_fanout平均 Fanout 值
total含集群路由后的全局订阅总数

示例响应 ​

json
{
  "num_subscriptions": 256,
  "num_cache": 128,
  "num_inserts": 10000,
  "num_removes": 9744,
  "num_matches": 5000000,
  "cache_hit_rate": 0.987,
  "max_fanout": 50,
  "avg_fanout": 1.5,
  "total": 768
}

使用场景 ​

bash
# 查看订阅统计摘要
curl -s http://nats:8222/subsz | jq '{
  subscriptions: .num_subscriptions,
  cache_hit_rate: .cache_hit_rate,
  max_fanout: .max_fanout,
  avg_fanout: .avg_fanout
}'

# 测试某个 Subject 会被哪些订阅接收
curl -s "http://nats:8222/subsz?test=orders.placed" | jq .

6. /jsz — JetStream 状态 ​

URL: GET http://nats-server:8222/jsz

说明: JetStream 的核心监控端点,提供 JetStream 引擎状态、Meta Cluster 的 Raft 状态、存储用量等关键信息。

关键字段解释 ​

字段说明
config.max_memoryJetStream 最大内存使用配置(字节)
config.max_storageJetStream 最大磁盘使用配置(字节)
config.store_dirJetStream 数据存储目录
memory当前内存使用量(字节)
storage当前磁盘使用量(字节)
reserved_memory预留内存(尚未实际使用)
reserved_storage预留磁盘(尚未实际使用)
accounts启用 JetStream 的账号数量
ha_assetsHA 资源数量(Replicas>1 的 Stream 和 Consumer 之和)
api.totalJetStream API 累计调用次数
api.errorsJetStream API 累计错误次数
meta_cluster.name集群名称
meta_cluster.leader当前 Meta Raft Leader 节点名
meta_cluster.peer本节点在集群中的 Peer ID
meta_cluster.replicas集群所有节点的 Raft 状态列表
meta_cluster.replicas[].name节点名称
meta_cluster.replicas[].current是否跟上 Leader(true=已同步)
meta_cluster.replicas[].active距最后一次 Raft 活动的时间
meta_cluster.replicas[].lag日志落后 Leader 的条目数(应接近 0)
streams本节点负责的 Stream 总数
consumers本节点负责的 Consumer 总数
messages所有 Stream 的消息总数
bytes所有 Stream 的存储字节总量

示例响应(部分) ​

json
{
  "server_id": "NBQXXX-NODE-1",
  "now": "2024-01-15T10:30:00Z",
  "config": {
    "max_memory": 4294967296,
    "max_storage": 107374182400,
    "store_dir": "/data/nats/jetstream",
    "sync_always": false,
    "sync_interval": 2000000000,
    "compress_ok": true
  },
  "memory": 104857600,
  "storage": 10737418240,
  "reserved_memory": 0,
  "reserved_storage": 0,
  "accounts": 1,
  "ha_assets": 9,
  "api": {
    "total": 12345,
    "errors": 3
  },
  "meta_cluster": {
    "name": "prod-cluster",
    "leader": "nats-node-1",
    "peer": "NQJXXX...",
    "replicas": [
      {
        "name": "nats-node-1",
        "current": true,
        "active": "50ms",
        "lag": 0
      },
      {
        "name": "nats-node-2",
        "current": true,
        "active": "60ms",
        "lag": 0
      },
      {
        "name": "nats-node-3",
        "current": true,
        "active": "55ms",
        "lag": 0
      }
    ]
  },
  "streams": 5,
  "consumers": 12,
  "messages": 2500000,
  "bytes": 10737418240
}

使用场景 ​

bash
# 查看 JetStream 健康摘要
curl -s http://nats:8222/jsz | jq '{
  meta_leader: .meta_cluster.leader,
  streams: .streams,
  consumers: .consumers,
  messages: .messages,
  storage_gb: (.storage / 1073741824 | . * 100 | round / 100),
  api_errors: .api.errors,
  ha_assets: .ha_assets
}'

# 检查 Meta Cluster 所有节点是否同步(lag 应为 0)
curl -s http://nats:8222/jsz | jq '.meta_cluster.replicas[] | {name, current, lag, active}'

# 计算 JetStream 存储使用率
curl -s http://nats:8222/jsz | jq '{
  used_gb: (.storage / 1073741824 | . * 100 | round / 100),
  max_gb: (.config.max_storage / 1073741824 | . * 100 | round / 100),
  usage_pct: (.storage / .config.max_storage * 100 | . * 10 | round / 10)
}'

7. /jsz?streams=1 — 包含 Stream 列表 ​

URL: GET http://nats-server:8222/jsz?streams=1

说明: 在 /jsz 基础上,附加返回所有 Stream 的详细配置和运行状态(包含 Raft 副本状态)。数据量较大,适合定期采集而非实时查询。

额外字段 ​

返回的 JSON 在 /jsz 基础上增加 account_details[].stream_detail 数组:

json
{
  "account_details": [
    {
      "name": "$G",
      "stream_detail": [
        {
          "name": "ORDERS",
          "created": "2024-01-01T00:00:00Z",
          "config": {
            "name": "ORDERS",
            "subjects": ["orders.>"],
            "retention": "limits",
            "max_consumers": -1,
            "max_msgs": 10000000,
            "max_bytes": 10737418240,
            "max_age": 604800000000000,
            "max_msg_size": 1048576,
            "storage": "file",
            "replicas": 3,
            "no_ack": false,
            "discard": "old"
          },
          "state": {
            "messages": 50000,
            "bytes": 10485760,
            "first_seq": 1,
            "first_ts": "2024-01-10T00:00:00Z",
            "last_seq": 50000,
            "last_ts": "2024-01-15T10:29:59Z",
            "num_deleted": 0,
            "num_subjects": 10,
            "consumer_count": 3
          },
          "cluster": {
            "name": "prod-cluster",
            "leader": "nats-node-2",
            "replicas": [
              { "name": "nats-node-1", "current": true,  "active": "20ms", "lag": 0 },
              { "name": "nats-node-3", "current": true,  "active": "22ms", "lag": 0 }
            ]
          }
        }
      ]
    }
  ]
}

使用场景 ​

bash
# 列出所有 Stream 及其 Leader 分布
curl -s "http://nats:8222/jsz?streams=1" | \
  jq '.account_details[0].stream_detail[] | {
    name: .config.name,
    messages: .state.messages,
    bytes_mb: (.state.bytes / 1048576 | floor),
    leader: .cluster.leader,
    replicas: .config.replicas
  }'

# 检查所有 Stream 中是否有副本落后(lag > 0)
curl -s "http://nats:8222/jsz?streams=1" | \
  jq '.account_details[0].stream_detail[] |
      { stream: .config.name,
        lagging_replicas: [
          .cluster.replicas[]? | select(.lag > 100) |
          {name, lag, active}
        ]
      } | select(.lagging_replicas | length > 0)'

8. /jsz?consumers=1 — 包含 Consumer 列表 ​

URL: GET http://nats-server:8222/jsz?consumers=1

说明: 在 ?streams=1 基础上,进一步包含每个 Stream 下所有 Consumer 的详细状态,包含消费进度和积压量。

Consumer 关键字段 ​

json
{
  "name": "order-processor",
  "stream_name": "ORDERS",
  "created": "2024-01-10T00:00:00Z",
  "config": {
    "durable_name": "order-processor",
    "deliver_policy": "all",
    "ack_policy": "explicit",
    "ack_wait": 30000000000,
    "max_deliver": 3,
    "filter_subject": "orders.placed",
    "max_ack_pending": 1000
  },
  "delivered": {
    "consumer_seq": 45000,
    "stream_seq": 45000,
    "last_active": "2024-01-15T10:29:59Z"
  },
  "ack_floor": {
    "consumer_seq": 44900,
    "stream_seq": 44900,
    "last_active": "2024-01-15T10:29:58Z"
  },
  "num_ack_pending": 100,
  "num_redelivered": 5,
  "num_waiting": 0,
  "num_pending": 1000,
  "cluster": {
    "leader": "nats-node-2"
  }
}
字段说明
num_pending未被 Consumer 消费的消息数(消费积压量)
num_ack_pending已投递但尚未 ACK 的消息数(处理中)
num_redelivered因超时重投的消息数(>0 表示有处理失败)
num_waiting等待新消息的 Pull Consumer 请求数
delivered.stream_seq已投递的最新 Stream 序列号
ack_floor.stream_seq已 ACK 的最低序列号(之前的消息都已 ACK)

使用场景 ​

bash
# 查看所有 Consumer 的消费积压(num_pending > 0 表示有积压)
curl -s "http://nats:8222/jsz?consumers=1" | \
  jq '[.account_details[0].stream_detail[].consumer_detail[]? |
       {stream: .stream_name, consumer: .name, pending: .num_pending,
        ack_pending: .num_ack_pending, redelivered: .num_redelivered}] |
      sort_by(-.pending)'

# 找出积压超过 1000 条的 Consumer(需要扩容处理)
curl -s "http://nats:8222/jsz?consumers=1" | \
  jq '[.account_details[0].stream_detail[].consumer_detail[]? |
       select(.num_pending > 1000) |
       {stream: .stream_name, consumer: .name, pending: .num_pending}]'

# 检查重投消息(num_redelivered 高表示处理失败率高)
curl -s "http://nats:8222/jsz?consumers=1" | \
  jq '[.account_details[0].stream_detail[].consumer_detail[]? |
       select(.num_redelivered > 0) |
       {consumer: .name, redelivered: .num_redelivered}]'

9. /healthz — 健康检查 ​

NATS 提供多个 /healthz 变体,分别适用于不同的探针场景。

9.1 /healthz — 基础健康检查 ​

URL: GET http://nats-server:8222/healthz

说明: 最基础的健康检查,只要 NATS Server 进程正常运行就返回 200 OK。

json
{ "status": "ok", "healthz": "ok" }

HTTP 状态码:

  • 200 — 服务器正常
  • 503 — 服务器不健康

适用探针: Kubernetes liveness probe(存活探针)

yaml
livenessProbe:
  httpGet:
    path: /healthz
    port: 8222
  initialDelaySeconds: 10
  periodSeconds: 30
  failureThreshold: 3

9.2 /healthz?js-server-only=true — JetStream 本节点健康 ​

URL: GET http://nats-server:8222/healthz?js-server-only=true

说明: 检查本节点的 JetStream 是否已初始化就绪。与 ?js-enabled-only=true 不同,此选项不等待 Meta Cluster 选出 Leader,只检查本节点 JetStream 引擎是否已启动。

推荐用于: Kubernetes readiness probe(就绪探针)

yaml
readinessProbe:
  httpGet:
    path: /healthz?js-server-only=true
    port: 8222
  initialDelaySeconds: 5
  periodSeconds: 10
  failureThreshold: 3

为什么推荐 js-server-only=true 而不是默认 /healthz?

在 NATS 集群启动时,各节点需要一段时间完成 Raft 选举。使用 js-server-only=true 可以让节点在本地 JetStream 就绪后立即接受流量,而不必等待整个集群选举完成(这可能需要几秒到几十秒)。这能减少滚动部署时的等待时间。

9.3 /healthz?js-enabled-only=true — JetStream 是否启用 ​

URL: GET http://nats-server:8222/healthz?js-enabled-only=true

说明: 检查 JetStream 是否已启用并完全就绪(包括等待 Meta Cluster 选出 Leader)。在集群刚启动时,此检查可能返回 503,直到集群完成选举。

适用场景: 用于验证集群 JetStream 已完全可用的一次性检查(不适合做 readiness probe,因为可能长时间 503)

bash
# 等待集群完全就绪
until curl -sf "http://nats:8222/healthz?js-enabled-only=true"; do
  echo "等待 JetStream 就绪..."
  sleep 2
done
echo "JetStream 已就绪"

9.4 健康检查响应状态对比 ​

端点200 条件503 条件适用场景
/healthz进程存活进程崩溃Liveness Probe
/healthz?js-server-only=true本节点 JetStream 启动本节点 JetStream 未启动Readiness Probe
/healthz?js-enabled-only=true集群 JetStream 就绪集群 JetStream 未就绪部署验证

10. /leafz — Leaf Node 连接 ​

URL: GET http://nats-server:8222/leafz

说明: 返回所有 Leaf Node 连接的详情。Leaf Node 是一种轻量级的 NATS Server,用于边缘场景或多云连接,通过单一 TLS 出站连接接入中心集群。

关键字段 ​

json
{
  "now": "2024-01-15T10:30:00Z",
  "leafnodes": 3,
  "leaves": [
    {
      "name": "edge-beijing",
      "is_spoke": false,
      "account": "$G",
      "ip": "1.2.3.4",
      "port": 7422,
      "rtt": "15ms",
      "in_msgs": 100000,
      "out_msgs": 50000,
      "subscriptions": 10
    }
  ]
}
字段说明
leafnodes当前连接的 Leaf Node 总数
leaves[].nameLeaf Node 名称
leaves[].is_spoke本节点是否是 Spoke(出站连接发起方)
leaves[].rtt与 Leaf Node 的网络延迟
leaves[].subscriptions通过此 Leaf 传播的订阅数

11. /gatewayz — Gateway 连接 ​

URL: GET http://nats-server:8222/gatewayz

说明: 在多集群(Super Cluster)架构中,Gateway 是集群间的互联通道。此端点返回所有 Gateway 连接状态。

关键字段 ​

json
{
  "server_id": "NBQXXX-NODE-1",
  "now": "2024-01-15T10:30:00Z",
  "name": "cluster-beijing",
  "outbound_gateways": {
    "cluster-shanghai": {
      "connection": {
        "name": "cluster-shanghai",
        "ip": "1.2.3.4",
        "port": 7522,
        "rtt": "5ms",
        "uptime": "10h",
        "in_msgs": 500000,
        "out_msgs": 600000
      }
    }
  },
  "inbound_gateways": {
    "cluster-shanghai": [
      {
        "connection": {
          "name": "cluster-shanghai-node-1",
          "ip": "1.2.3.5",
          "rtt": "5ms"
        }
      }
    ]
  }
}

12. /accountz — 账号信息 ​

URL: GET http://nats-server:8222/accountz

参数: ?acc=ACCOUNT_NAME — 查询指定账号的详情

说明: 返回 NATS 账号信息,在多租户(Multi-tenancy)场景中用于查看各账号的资源使用情况和 JetStream 配额。

bash
# 列出所有账号
curl -s http://nats:8222/accountz | jq '.accounts | keys'

# 查看特定账号的 JetStream 使用情况
curl -s "http://nats:8222/accountz?acc=myapp" | jq '{
  subscriptions: .subscriptions,
  conns: .conns,
  js_mem: .jetstream.memory,
  js_storage: .jetstream.storage,
  js_streams: .jetstream.streams,
  js_consumers: .jetstream.consumers
}'

13. /statz — 统计信息 ​

URL: GET http://nats-server:8222/statz

说明: 与 /varz 类似,但专注于统计指标,适合 Prometheus 采集前的原始数据确认。

bash
curl -s http://nats:8222/statz | jq '{
  connections: .connections,
  in_msgs: .in_msgs,
  out_msgs: .out_msgs,
  in_bytes: .in_bytes,
  out_bytes: .out_bytes,
  slow_consumers: .slow_consumers
}'

14. 常用运维命令集合 ​

以下命令组合了 curl + jq,可直接在 Shell 中执行。

14.1 检查集群整体健康 ​

bash
#!/bin/bash
# cluster-health-check.sh
# 对集群所有节点执行健康检查

NODES=("nats-1:8222" "nats-2:8222" "nats-3:8222")

echo "=== 集群健康检查 $(date '+%Y-%m-%d %H:%M:%S') ==="

for NODE in "${NODES[@]}"; do
  echo ""
  echo "--- 节点: $NODE ---"

  # 1. 基础存活检查
  STATUS=$(curl -sf "http://$NODE/healthz" | jq -r '.status' 2>/dev/null || echo "UNREACHABLE")
  echo "健康状态: $STATUS"

  if [ "$STATUS" = "UNREACHABLE" ]; then
    echo "节点无法访问,跳过详情检查"
    continue
  fi

  # 2. 服务器基础信息
  curl -s "http://$NODE/varz" | jq '{
    version,
    uptime,
    connections,
    slow_consumers,
    mem_mb: (.mem / 1048576 | floor)
  }'

  # 3. JetStream 状态
  echo "JetStream 状态:"
  curl -s "http://$NODE/jsz" | jq '{
    meta_leader: .meta_cluster.leader,
    streams: .streams,
    consumers: .consumers,
    ha_assets: .ha_assets,
    api_errors: .api.errors,
    storage_gb: (.storage / 1073741824 | . * 10 | round / 10)
  }'

  # 4. Meta Cluster Raft 状态
  echo "Meta Cluster Raft 状态:"
  curl -s "http://$NODE/jsz" | jq '.meta_cluster.replicas[] | {name, current, lag, active}'
done

14.2 查询所有 Stream 摘要 ​

bash
#!/bin/bash
# list-streams.sh

NODE="${1:-nats-1:8222}"

echo "=== Stream 列表 ==="
curl -s "http://$NODE/jsz?streams=1" | \
  jq -r '.account_details[0].stream_detail[] |
    [.config.name,
     .config.replicas,
     .state.messages,
     (.state.bytes / 1048576 | floor | tostring) + "MB",
     (.cluster.leader // "N/A")] |
    @tsv' | \
  column -t -s $'\t' -N "NAME,REPLICAS,MESSAGES,STORAGE,LEADER"

14.3 查询指定 Stream 的 Consumer 列表 ​

bash
#!/bin/bash
# list-consumers.sh <stream-name>

NODE="${2:-nats-1:8222}"
STREAM="${1:?请指定 Stream 名称}"

echo "=== Stream: $STREAM 的 Consumer 列表 ==="
curl -s "http://$NODE/jsz?consumers=1" | \
  jq -r --arg stream "$STREAM" '
    .account_details[0].stream_detail[] |
    select(.config.name == $stream) |
    .consumer_detail[] |
    [.name,
     (.config.deliver_policy // "all"),
     .num_pending,
     .num_ack_pending,
     .num_redelivered,
     (.cluster.leader // "N/A")] |
    @tsv' | \
  column -t -s $'\t' -N "CONSUMER,POLICY,PENDING,ACK_PENDING,REDELIVERED,LEADER"

14.4 查询消费进度(积压分析) ​

bash
#!/bin/bash
# consumer-lag.sh

NODE="${1:-nats-1:8222}"

echo "=== Consumer 消费积压分析 $(date '+%H:%M:%S') ==="
echo ""

curl -s "http://$NODE/jsz?consumers=1" | \
  jq -r '
    .account_details[0].stream_detail[] |
    .consumer_detail[]? |
    [.stream_name,
     .name,
     .num_pending,
     .num_ack_pending,
     .num_redelivered,
     (if .num_pending > 10000 then "CRITICAL"
      elif .num_pending > 1000 then "WARNING"
      else "OK" end)] |
    @tsv' | \
  sort -t$'\t' -k3 -rn | \
  column -t -s $'\t' -N "STREAM,CONSUMER,PENDING,ACK_PENDING,REDELIVERED,STATUS"

14.5 检查慢消费者 ​

bash
#!/bin/bash
# slow-consumers.sh

NODE="${1:-nats-1:8222}"

echo "=== 慢消费者检测 ==="
SLOW=$(curl -s "http://$NODE/connz?limit=200" | \
  jq '[.connections[] | select(.pending_bytes > 0) |
       {name, ip, lang, pending_kb: (.pending_bytes / 1024 | floor),
        subscriptions}] |
      sort_by(-.pending_kb)')

COUNT=$(echo "$SLOW" | jq 'length')

if [ "$COUNT" -eq 0 ]; then
  echo "没有慢消费者,一切正常"
else
  echo "发现 $COUNT 个慢消费者:"
  echo "$SLOW" | jq -r '.[] | [.name, .ip, .lang, (.pending_kb | tostring) + "KB"] | @tsv' | \
    column -t -s $'\t' -N "NAME,IP,LANG,PENDING"
fi

14.6 实时监控连接数变化 ​

bash
#!/bin/bash
# watch-connections.sh

NODE="${1:-nats-1:8222}"
INTERVAL="${2:-5}"

echo "实时监控连接数(每 ${INTERVAL}s 刷新,Ctrl+C 退出)"
echo ""

PREV_IN=0
PREV_OUT=0

while true; do
  DATA=$(curl -s "http://$NODE/varz")
  CONNS=$(echo "$DATA" | jq '.connections')
  IN=$(echo "$DATA" | jq '.in_msgs')
  OUT=$(echo "$DATA" | jq '.out_msgs')
  SLOW=$(echo "$DATA" | jq '.slow_consumers')
  MEM=$(echo "$DATA" | jq '(.mem / 1048576 | floor)')

  IN_RATE=$(( (IN - PREV_IN) / INTERVAL ))
  OUT_RATE=$(( (OUT - PREV_OUT) / INTERVAL ))

  printf "[%s] 连接数: %-5s  慢消费者: %-3s  内存: %-6sMB  消息/s: in=%-8s out=%-8s\n" \
    "$(date '+%H:%M:%S')" "$CONNS" "$SLOW" "$MEM" "$IN_RATE" "$OUT_RATE"

  PREV_IN=$IN
  PREV_OUT=$OUT
  sleep "$INTERVAL"
done

14.7 Kubernetes 探针配置完整示例 ​

yaml
# nats StatefulSet 探针配置
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nats
spec:
  template:
    spec:
      containers:
      - name: nats
        image: nats:2.10-alpine
        ports:
        - containerPort: 4222  # 客户端
        - containerPort: 6222  # 集群路由
        - containerPort: 8222  # 监控 HTTP

        # 存活探针:进程级别,失败则重启容器
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8222
          initialDelaySeconds: 10
          periodSeconds: 30
          timeoutSeconds: 5
          failureThreshold: 3

        # 就绪探针:JetStream 本节点就绪后才接受流量
        readinessProbe:
          httpGet:
            path: /healthz?js-server-only=true
            port: 8222
          initialDelaySeconds: 5
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3

        # 启动探针:给 JetStream 足够时间初始化(大量数据时恢复较慢)
        startupProbe:
          httpGet:
            path: /healthz
            port: 8222
          initialDelaySeconds: 5
          periodSeconds: 5
          timeoutSeconds: 5
          failureThreshold: 30  # 最多等待 30*5=150s

15. 告警指标建议 ​

15.1 使用 nats-prometheus-exporter ​

bash
# 安装
go install github.com/nats-io/prometheus-nats-exporter@latest

# 启动(采集所有端点)
prometheus-nats-exporter \
  -varz -jsz -connz -routez \
  -addr 0.0.0.0 \
  -port 7777 \
  http://nats-1:8222 http://nats-2:8222 http://nats-3:8222

15.2 核心告警规则(Prometheus AlertManager) ​

yaml
# nats-alerts.yaml
groups:
  - name: nats_critical
    rules:

      # 节点不可达
      - alert: NATSNodeDown
        expr: up{job="nats"} == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "NATS 节点不可达: {{ $labels.instance }}"
          description: "NATS 节点已超过 1 分钟无法访问"

      # 慢消费者出现
      - alert: NATSSlowConsumers
        expr: gnatsd_varz_slow_consumers > 0
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "NATS 存在慢消费者: {{ $value }} 个"
          description: "存在积压未消费消息的连接,可能导致消息堆积"

      # JetStream 存储使用率过高
      - alert: JetStreamStorageHigh
        expr: (gnatsd_jsz_storage / gnatsd_jsz_config_max_storage) * 100 > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "JetStream 存储使用率 {{ $value | humanizePercentage }}"
          description: "JetStream 磁盘使用超过 80%,请及时清理或扩容"

      - alert: JetStreamStorageCritical
        expr: (gnatsd_jsz_storage / gnatsd_jsz_config_max_storage) * 100 > 95
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "JetStream 存储紧急: {{ $value | humanizePercentage }}"

      # JetStream API 错误率
      - alert: JetStreamAPIErrors
        expr: increase(gnatsd_jsz_api_errors[5m]) > 10
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "JetStream API 错误数增加: {{ $value }} 次/5min"

      # Consumer 消费积压
      - alert: ConsumerLagHigh
        expr: nats_consumer_num_pending > 10000
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Consumer {{ $labels.consumer_name }} 积压 {{ $value }} 条消息"

      - alert: ConsumerLagCritical
        expr: nats_consumer_num_pending > 100000
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Consumer {{ $labels.consumer_name }} 严重积压 {{ $value }} 条"

      # Meta Cluster 副本落后
      - alert: JetStreamMetaRaftLag
        expr: nats_meta_cluster_replica_lag > 1000
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "JetStream Meta Raft 副本落后 {{ $value }} 条日志"

      # 连接数接近上限
      - alert: NATSConnectionsHigh
        expr: (gnatsd_varz_connections / gnatsd_varz_max_connections) * 100 > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "NATS 连接数使用率 {{ $value | humanizePercentage }}"

      # 路由数量异常(应等于集群节点数 - 1)
      - alert: NATSRoutesMissing
        expr: gnatsd_routez_num_routes < 2
        for: 3m
        labels:
          severity: critical
        annotations:
          summary: "NATS 集群路由丢失,当前只有 {{ $value }} 条路由(期望 2)"

15.3 Grafana Dashboard 推荐指标 ​

面板名称指标说明
连接数趋势gnatsd_varz_connections监控连接数变化
消息吞吐rate(gnatsd_varz_in_msgs[1m])每秒消息接收数
内存使用gnatsd_varz_mem内存趋势
JetStream 存储gnatsd_jsz_storage磁盘使用趋势
Consumer 积压nats_consumer_num_pending按 Consumer 分组
慢消费者数gnatsd_varz_slow_consumers应始终为 0
Raft 副本落后nats_stream_cluster_replica_lag应始终为 0
Meta Leadernats_meta_cluster_leader监控 Leader 切换
API 错误率rate(gnatsd_jsz_api_errors[5m])应接近 0

15.4 监控最佳实践 ​

1. 采集频率:建议 15s 采集一次 /varz,60s 采集一次 /jsz?consumers=1(后者数据量大)

2. 关键 SLI 指标:
   - 可用性:节点存活率 >= 99.9%
   - 消费延迟:Consumer num_pending < 10000(正常业务流量)
   - 持久化延迟:Publish 到 PubAck 的 p99 < 50ms

3. 数据保留:Prometheus 保留 15 天,用于趋势分析和容量规划

4. 告警分级:
   - CRITICAL:立即响应(页面通知),影响服务可用性
   - WARNING:工作时间处理,影响性能但不影响可用性

5. 监控端点安全:生产环境应限制 8222 端口只对内网访问,避免暴露业务信息