Statsd 0.10.2 常用 CLI 命令与工具详解
Statsd 参考实现运维命令全实测:nc 手工发送行协议四类指标(counter@采样/timer多行/gauge增减94/set去重/坏行)、TCP 8126 管理口逐条命令(stats/counters/gauges/timers/config/health/delcounters/quit/ERROR)、systemd 生命周期与 Final Flush、proxy.js 集群代理(status/哈希转发到 statsd02:18125)、utils 三脚本(check_statsd.pl OK/WARNING、check_statsd_health 挂起坑、timer-metric-counts),含速查表与排障实录。
Statsd 0.10.2 常用 CLI 命令与工具详解
目标:把 StatsD 参考实现(statsd/statsd)日常运维要敲的命令一次讲完——启动/停止入口命令、用
nc手工发送行协议、TCP 8126 管理口逐条命令实测(stats/counters/gauges/timers/config/health/delcounters/quit)、集群代理proxy.js实测,以及utils/目录三个 Nagios 检查脚本的用法与坑。全部回显为 2026-11-01 在 Ubuntu 24.04.5 服务器(statsd01,源码 v0.10.2,systemd 主实例监听 UDP 8125 / TCP 8126;statsd02,npm 0.9.0 实例监听 18125/18126)上的实测记录。前置:安装见 《Ubuntu 24.04 安装 Statsd 0.10.2 指南》,参数含义见 《Statsd 0.10.2 配置参数详解》,架构背景见 《Statsd 介绍与选型指南》。
一、进程入口与生命周期命令
StatsD 没有功能型子命令(无 --version/status 之类 CLI),CLI 面就是"入口脚本 + 配置文件":
node stats.js /etc/statsd/config.js # 源码通道守护进程(npm 通道等价命令:statsd /etc/statsd/config.js)
node proxy.js /tmp/proxyConfig.js # 集群代理(独立入口,见第五节)
生产上由 systemd 托管(单元文件与启用过程见安装篇第四节),日常生命周期命令实测:
root@statsd01:~# systemctl status statsd # active (running),Main PID 7726 "statsd /etc/statsd/config.js"
root@statsd01:~# systemctl stop statsd
root@statsd01:~# journalctl -u statsd --no-pager | grep -E "Final Flush|Stopped|Stopping" | tail -4
Nov 01 10:35:02 statsd01 systemd[1]: Stopping statsd.service - StatsD metrics aggregation daemon...
Nov 01 10:35:02 statsd01 node[7726]: 1 Nov 10:35:02 - Starting Final Flush
Nov 01 10:35:02 statsd01 systemd[1]: Stopped statsd.service - StatsD metrics aggregation daemon.
root@statsd01:~# systemctl start statsd
root@statsd01:~# systemctl is-active statsd
active
要点:SIGTERM 会触发 Final Flush(未满一个周期的窗口数据先刷给后端再退出),所以停止务必走 systemctl stop/kill(默认 SIGTERM),不要 kill -9——那会丢掉整个内存窗口。手工前台实例同样验证过:kill $PID 后日志尾部再次打印完整聚合 JSON 才退出。
二、行协议:用 nc 手工发送指标
协议一行一条:<name>:<value>|<type>[@sample_rate][#tag:v]。对主实例 8125 的实测发送序列:
root@statsd01:~# echo "d1c:1|c" | nc -u -w0 127.0.0.1 8125
root@statsd01:~# echo "d1s:5|c|@0.1" | nc -u -w0 127.0.0.1 8125
root@statsd01:~# printf 'd1t:240|ms\nd1t:320|ms\n' | nc -u -w0 127.0.0.1 8125
root@statsd01:~# echo "d1g:100|g" | nc -u -w0 127.0.0.1 8125
root@statsd01:~# echo "d1g:-10|g" | nc -u -w0 127.0.0.1 8125
root@statsd01:~# echo "d1g:+4|g" | nc -u -w0 127.0.0.1 8125
root@statsd01:~# printf 'd1u:uid1|s\nd1u:uid2|s\nd1u:uid1|s\n' | nc -u -w0 127.0.0.1 8125
root@statsd01:~# echo "d1bad-not-valid" | nc -u -w0 127.0.0.1 8125
四类指标语义在回显里各自得到验证:
- counter:
d1c:1|c计 1 次;d1s:5|c|@0.1带 10% 采样率,服务端按5/0.1=50还原(README 经典示例gorets:1|c|@0.1在 graphite 抓包里同样还原为stats_counts.gorets 50); - timer:一个 UDP 包用
\n携带两条d1t样本,聚合出全套分位统计; - gauge:带符号值做增减(100→-10→+4),管理口
gauges实测结果:
root@statsd01:~# echo gauges | nc -w1 127.0.0.1 8126
{ 'statsd.timestamp_lag': 0, d1g: 94 }
END
- set:
uid1/uid2/uid1三个成员去重为 2;graphite 抓包对应stats.sets.uniques.count 1(README 示例实测); - 坏行:
d1bad-not-valid无|type,被计入statsd.bad_lines_seen(管理口stats的messages.bad_lines_seen随之 +1,见下节 A1 对比)。
💡 技术拓展:
nc -u -w0发 UDP 是"发完即走",与真实客户端 SDK 行为一致;statsd 对 UDP 没有任何回执,发送侧看不到错误——验证协议是否发对,只能靠管理口 counters 或后端抓包,这也是本节把nc与8126搭配讲的原因。
三、管理口(TCP 8126)命令逐条实测
memcached 风格纯文本协议,每条命令以 END 结束。无认证,端口必须网络隔离。官方 docs/admin_interface.md 列出的命令与实测结果如下。
3.1 stats——服务自观测
发送协议序列前:
root@statsd01:~# echo stats | nc -w1 127.0.0.1 8126
uptime: 2579
messages.last_msg_seen: 2250
messages.bad_lines_seen: 0
graphite.last_flush: 2239
graphite.last_exception: 1793529103
graphite.flush_time: 0
graphite.flush_length: 832
console.lastFlush: 1793526524
console.lastException: 1793526524
END
发送序列后(注意 bad_lines_seen 0→1、last_msg_seen 归零、last_flush 推进):
uptime: 2580
messages.last_msg_seen: 0
messages.bad_lines_seen: 1
graphite.last_flush: 2240
每个后端还各自发布 graphite.last_flush/last_exception/flush_time/flush_length——判断"statsd 活着但 Graphite 收不到数"就看 last_exception 是否在推进。
3.2 counters / gauges / timers——内存桶快照
root@statsd01:~# echo counters | nc -w1 127.0.0.1 8126
{
'statsd.bad_lines_seen': 0,
'statsd.packets_received': 0,
'statsd.metrics_received': 0,
bad_key2: 0,
'tagged;env=prod;host=web01': 0,
d1c: 0,
d1s: 0
}
END
root@statsd01:~# echo timers | nc -w1 127.0.0.1 8126
{ d1t: [] }
END
三个 dump 命令输出的是 Node 对象字面量(无 END 之外的格式化保证)。flush 后速率归 0、timer 样本清空,符合"窗口聚合后重置"语义。
3.3 config——生效配置 dump
root@statsd01:~# echo config | nc -w1 127.0.0.1 8126 | head -16
graphitePort: 2003
graphiteHost: 127.0.0.1
port: 8125
backends > 0: ./backends/graphite
backends > 1: ./backends/console
debug: true
输出为"默认值+显式配置"的合并生效值(完整解读见配置篇 1.2)。⚠️ 该命令会把配置全量明文吐出(含后端地址),管理口暴露面等于配置泄露面,隔离要更严。
3.4 health——查/设摘流标志
root@statsd01:~# echo health | nc -w1 127.0.0.1 8126
health: up
root@statsd01:~# echo "health down" | nc -w1 127.0.0.1 8126
root@statsd01:~# echo health | nc -w1 127.0.0.1 8126
health: down
root@statsd01:~# echo "health up" | nc -w1 127.0.0.1 8126
root@statsd01:~# echo health | nc -w1 127.0.0.1 8126
health: up
health [up|down] 单独执行是查询,带参数是设置——给 LB/keepalived 做 statsd 摘流的标准钩子(注意配置篇 8.2:启动参数 healthStatus 实测不影响该命令返回值)。
3.5 delcounters / delgauges / deltimers——删桶
root@statsd01:~# echo "d1tmp:1|c" | nc -u -w0 127.0.0.1 8125
root@statsd01:~# echo counters | nc -w1 127.0.0.1 8126 | grep d1tmp
d1tmp: 1
root@statsd01:~# echo "delcounters d1tmp" | nc -w1 127.0.0.1 8126
deleted: d1tmp
END
root@statsd01:~# echo counters | nc -w1 127.0.0.1 8126 | grep -c d1tmp
0
支持删单个 key 或通配文件夹(官方文档示例:delcounters sandbox.test.*)。delgauges/deltimers 同族语法。这是运行时清高基数污染桶的直接手段(预防手段是配置 deleteIdleStats)。
3.6 不存在的命令与 quit
root@statsd01:~# echo sets | nc -w1 127.0.0.1 8126 | head -5
ERROR
root@statsd01:~# echo quit | nc -w1 127.0.0.1 8126; echo "nc-exit=$?"
nc-exit=0
root@statsd01:~# echo foobar | nc -w1 127.0.0.1 8126 | head -3
ERROR
实测确认:没有 sets dump 命令(set 数据只能从后端侧看),未知命令一律回 ERROR;quit 由服务端关闭连接(nc 正常退出码 0)。
四、utils/ 监控检查脚本
4.1 check_statsd.pl——Nagios 阈值检查(实测可用)
Perl 版通用检查:连管理口取 stats 里任意指标做阈值判断。实测 OK 与 WARNING 两态:
root@statsd01:~# perl /opt/statsd/utils/check_statsd.pl --host 127.0.0.1 --port 8126 --metric "graphite.last_flush" --warning 15 --crit 30
OK: graphite.last_flush = 8
exit=0
主实例空闲一段时间后再跑(last_flush 距今 309 秒,超过 warning 15):
WARNING: graphite.last_flush value 309 exceeds warning threshold 15
exit=1
退出码遵循 Nagios 约定(0=OK/1=WARNING),--metric 可指任意 stats 输出字段(messages.bad_lines_seen、graphite.last_exception 都是黄金监控项)。
4.2 check_statsd_health——官方 bash 健康检查(有坑)
直接执行会挂住不返回:脚本内部用 nc 连管理口但不带关闭参数,而 8126 是长连接、不会主动断开。实测:
root@statsd01:~# timeout 3 bash /opt/statsd/utils/check_statsd_health
exit=124 # 124 = timeout 强杀,nc 不自动关闭
root@statsd01:~# bash /opt/statsd/utils/check_statsd_health
exit=143 # 后台运行后被 kill
替代方案:要么给脚本里的 nc 补 -w1,要么直接用一行式 echo health | nc -w1 127.0.0.1 8126 | grep -q '^health: up' 做探活。
4.3 statsd-timer-metric-counts.sh——timer 采样调优工具
跑在 Graphite 服务器上的 bash 工具(读 whisper 文件/调 render API),统计各 timer 指标一小时内收到的样本数,用来决策"哪些 key 该加大采样率"。脚本头部注释原文(要点):
# is your statsd machine maxing out cpu? ... unable to pull udp packets out of the buffer
# at a fast enough rate? (see `netstat -su` ) timer metrics are by far the most cpu intensive
# and tuning the sampling of those is key to keeping cpu load under control.
# this tool (to be run on your graphite server) shows for all your timing metric keys how many packets
# it accepted in a given interval like 1hour.
graphite_url=http://<your graphite url>
whisper_dir=/var/lib/carbon/whisper
timers_subdir=stats/timers
配合 statsd 侧的 percentThreshold/calculatedTimerMetrics(配置篇第五节)形成"客户端采样 + 服务端裁剪"的 CPU 治理组合。
五、集群代理 proxy.js 命令实测
多机水平扩展用仓库自带的 proxy.js(按指标名一致性哈希固定路由到后端 statsd 实例,带节点健康探测)。代理配置 /tmp/proxyConfig.js:
{
nodes: [ { host: 'statsd02', port: 18125, adminport: 18126 } ]
, server: './servers/udp'
, host: '0.0.0.0'
, port: 19151
, mgmt_port: 19152
, checkInterval: 1000
}
启动与日志:
root@statsd01:~# node proxy.js /tmp/proxyConfig.js
1 Nov 09:50:39 - [7854] reading config file: /tmp/proxyConfig.js
1 Nov 09:50:39 - INFO: [7854] server is up
(node:7854) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
代理自己的管理口(19152)只有 status 命令:
root@statsd01:~# echo status | nc -w1 127.0.0.1 19152
uptime: 2
nodes: statsd02:18125
向代理 19151 发 proxym:2|c 与 proxym2:7|ms,在后端实例 statsd02(18125)的 flush 里收到转发计数:
proxym: 0.2
以及 timers: { proxym2: [] } / timer_data: { proxym2: { count_ps: 0, count: 0 } }(样本已计入后完成窗口重置)。两点注意(官方 docs/cluster_proxy.md):后端 statsd 实例需配 deleteIdleStats: true(否则哈希路由下"闲置刷 0"会在所有节点扩散);checkInterval 内节点失联会重算哈希环。
六、日常运维命令速查
| 场景 | 命令 |
|---|---|
| 发计数器/计时/仪表/集合 | echo "k:1|c" | nc -u -w0 HOST 8125(ms/g/s 同理) |
| 带采样率 | echo "k:5|c|@0.1" | nc -u -w0 HOST 8125 |
| 标签指标 | echo "k:1|c|#env:prod" | nc -u -w0 HOST 8125 |
| 看服务健康 | echo stats | nc -w1 HOST 8126 |
| 看桶快照 | echo counters|gauges|timers | nc -w1 HOST 8126 |
| 看生效配置 | echo config | nc -w1 HOST 8126 |
| 摘流/挂回 | echo "health down|up" | nc -w1 HOST 8126 |
| 删污染桶 | echo "delcounters k.sub.*" | nc -w1 HOST 8126 |
| 探活(脚本用) | echo health | nc -w1 HOST 8126 | grep -q '^health: up' |
| Nagios 阈值 | perl utils/check_statsd.pl --host H --port 8126 --metric graphite.last_flush --warning 15 --crit 30 |
| 平滑停止 | systemctl stop statsd(触发 Final Flush,忌 kill -9) |
| 改配置生效 | 直接编辑 config.js(automaticConfigReload 默认热加载) |
七、命令面排障实录
nc连管理口不带-w1会挂死:8126 长连接不主动断开,echo stats | nc HOST 8126输出完仍等待;官方check_statsd_health正是栽在这点(4.2)。脚本化调用统一带-w1或发quit。sets命令不存在:想 dump set 桶会得ERROR(3.6),set 结果只能从后端输出看(stats.sets.<key>.count)。- 坏行静默:协议写错不报错、不回执,唯一痕迹是
messages.bad_lines_seen推进 + DEBUG 日志Bad line: …;上线初期用dumpMessages: true对照抓包(配置篇 8.3)。 health与healthStatus不一致:配置篇 8.2 实测healthStatus: "down"启动后health仍回 up——摘流以运行时命令为准。
至此,StatsD 参考实现的四块拼图完整:选型认知 → 安装部署 → 配置参数 → 命令运维。按顺序读前三篇(介绍与选型、安装指南、配置详解)即可从零到生产可用。