1. 数据收集的底层逻辑与整体设计思路
1.1 为什么数据采集是监控体系的生命线
监控系统本质上是一个"感知-判断-响应"的闭环,而数据采集就是这个闭环的起点。没有数据,告警是空谈,容量规划是拍脑袋,故障复盘是盲人摸象。我在多个项目中见过太多团队把精力花在告警规则调优和可视化大屏上,却忽略了采集层的基础质量,结果就是"垃圾进、垃圾出"——面板再漂亮,数据不准照样白搭。
Zabbix 4.0 作为一款成熟的分布式监控方案,它的数据采集体系有几个鲜明的设计特征:采集与存储解耦、主动与被动模式并存、支持多种采集协议。理解这些设计背后的取舍,比死记配置参数重要得多。
1.2 采集方式的分类与选型逻辑
Zabbix 的数据采集从宏观上分为三大类:
- Agent 采集:在目标主机上部署 Zabbix Agent,支持被动模式(Server 来拉)和主动模式(Agent 主动推)。这是最常用的方式,采集粒度细、指标丰富。
- Agentless 采集:不装 Agent,通过 SNMP、JMX、IPMI、SSH/Telnet 等协议采集。适合网络设备、Java 应用、带外管理卡等场景。
- 外部采集:通过 Zabbix Trapper、自定义脚本、外部检查等方式,把第三方数据灌进来。
选型的核心判断依据是三个问题:目标主机能不能装 Agent?采集频率要求多高?指标是标准化的还是业务自定义的?
我一般的经验法则是:能装 Agent 就装 Agent,因为主动模式的性能开销远低于 SNMP 轮询;网络设备没得选,只能走 SNMP;Java 应用优先 JMX,因为 JVM 内部指标只有 JMX 能拿到最全的。
1.3 主动模式与被动模式的性能账
这是很多新手容易忽略的关键点。被动模式下,Server 需要为每台主机维护轮询计划,采集 1000 台主机和采集 100 台主机,Server 端的压力差异是线性的。而主动模式下,Agent 自己按配置的刷新率上报,Server 只需要被动接收,压力曲线平缓得多。
我做过一个粗略的对比测试:同样 500 台主机、每台 50 个监控项、60 秒采集间隔,被动模式下 Server 的 CPU 占用大约在 40% 左右波动,而主动模式只有 15% 上下。这个差距在规模上到几千台时会更加明显。
注意:主动模式不是万能的。它要求 Agent 能主动连到 Server 的 10051 端口,网络策略上要放行。另外主动模式下 Server 无法即时触发一次采集,调试时不如被动模式直观。
2. 核心采集协议与实操要点拆解
2.1 Zabbix Agent 的主动与被动配置细节
Agent 的配置文件通常位于/etc/zabbix/zabbix_agentd.conf,几个关键参数决定了采集行为:
# 被动模式:允许哪些 Server 来拉数据 Server=192.168.1.100 # 主动模式:Agent 把数据推给谁 ServerActive=192.168.1.100 # 本机主机名,必须和 Web 端配置的 Host name 完全一致 Hostname=web-server-01 # 主动模式下的刷新率,单位秒 RefreshActiveChecks=120 # 采集并发数,被动模式下有效 StartAgents=3这里有个坑我踩过不止一次:Hostname参数和 Web 端的主机名必须一字不差,包括大小写。有一次批量部署时脚本里主机名带了空格,结果主动模式下数据死活上不来,排查了半天才发现是名字对不上。主动模式下 Agent 上报数据时会带上自己的 Hostname,Server 靠这个名字匹配主机,对不上就直接丢弃。
StartAgents这个参数也值得说道。它控制被动模式下 fork 多少个采集进程。默认是 3,如果监控项很多、采集频繁,可以适当调大,但不要超过 CPU 核数的两倍,否则进程切换开销反而拖慢采集。我一般按"监控项数量 / 50"来估算,比如 200 个监控项就设 4 到 5 个。
2.2 SNMP 采集的版本选择与 OID 定位
SNMP 是网络设备采集的主力协议。Zabbix 4.0 支持 v1、v2c、v3 三个版本。我的建议很明确:能用 v3 就用 v3,因为 v2c 的 community string 是明文传输的,安全性太差。
v3 的配置涉及几个参数:安全级别(noAuthNoPriv、authNoPriv、authPriv)、认证协议(MD5/SHA)、加密协议(DES/AES)。配置时最容易出错的是认证和加密协议的匹配,设备端和 Zabbix 端必须完全一致。
OID 的定位是个体力活。我通常的做法是先用snmpwalk把设备的 MIB 树走一遍,找到关键指标的 OID,再在 Zabbix 里配置。比如采集 Cisco 交换机的 CPU 利用率,OID 是1.3.6.1.4.1.9.2.1.56.0;采集接口流量,入口是1.3.6.1.2.1.2.2.1.10,出口是1.3.6.1.2.1.2.2.1.16。
# 走一遍系统描述,确认 SNMP 通了 snmpwalk -v 3 -u monitor -l authPriv -a SHA -A "authpass" -x AES -X "privpass" 192.168.1.1 1.3.6.1.2.1.1 # 采集接口流量示例 snmpget -v 2c -c public 192.168.1.1 1.3.6.1.2.1.2.2.1.10.1提示:SNMP 采集的间隔不要设得太短。很多网络设备的 SNMP 处理能力有限,30 秒一次已经算频繁了,60 秒是更稳妥的选择。设太短会导致设备 CPU 飙升,甚至 SNMP 进程崩溃。
2.3 JMX 采集 JVM 指标的实战配置
Java 应用的监控绕不开 JMX。Zabbix 通过 Java Gateway 来采集 JMX 数据,架构上是 Zabbix Server 把请求转发给 Java Gateway,Gateway 再连到目标 JVM 的 JMX 端口。
JVM 端启动时需要开启 JMX 远程访问:
java -Dcom.sun.management.jmxremote \ -Dcom.sun.management.jmxremote.port=9999 \ -Dcom.sun.management.jmxremote.authenticate=false \ -Dcom.sun.management.jmxremote.ssl=false \ -jar app.jar生产环境当然要开认证和 SSL,但调试阶段先关掉能省不少事。Java Gateway 的配置在/etc/zabbix/zabbix_java_gateway.conf:
LISTEN_IP="0.0.0.0" LISTEN_PORT=10052 START_POLLERS=5 TIMEOUT=30START_POLLERS是并发采集线程数,默认 5。如果 JMX 监控项很多,可以调到 10 到 20。TIMEOUT默认 3 秒,JMX 查询有时比较慢,建议调到 30 秒,否则容易超时。
JMX 采集的指标里,我最关注这几个:堆内存使用率、非堆内存使用率、GC 次数和耗时、线程数、类加载数。堆内存持续增长不回落,基本就是内存泄漏的信号;Full GC 频繁且耗时长,说明堆大小设置不合理或者对象创建速率过高。
2.4 自定义脚本采集与 Trapper 模式
有些业务指标是标准协议拿不到的,比如某个业务队列的积压数量、某个定时任务的执行状态。这时候就得靠自定义脚本加 Trapper 模式。
思路很简单:写个脚本采集数据,然后用zabbix_sender把数据推给 Server。
#!/bin/bash # 采集业务队列积压数 QUEUE_SIZE=$(some_command_to_get_queue_size) zabbix_sender -z 192.168.1.100 -s "app-server-01" -k "biz.queue.size" -o "$QUEUE_SIZE"Server 端需要先创建一个 Zabbix Trapper 类型的监控项,key 就是biz.queue.size。脚本可以放到 crontab 里定时执行,也可以用 Agent 的UserParameter配合主动模式。
UserParameter的写法:
# 在 zabbix_agentd.conf 或 conf.d 目录下的独立文件中 UserParameter=biz.queue.size[*],/usr/local/bin/check_queue.sh $1这种方式的好处是复用 Agent 的主动模式通道,不用额外管理 crontab,而且采集频率由 Zabbix 统一控制。
3. 完整采集流程的落地实现
3.1 从零搭建一套 Agent 采集的完整步骤
假设要给一台 Linux 应用服务器配置监控,采集 CPU、内存、磁盘、网络和进程状态。完整流程如下。
第一步,安装 Agent。以常见的包管理方式为例:
# 安装 Zabbix 官方源后 yum install -y zabbix-agent # 或 apt install -y zabbix-agent第二步,修改配置文件。核心是三个参数:Server、ServerActive、Hostname。
Server=192.168.1.100 ServerActive=192.168.1.100 Hostname=app-server-01第三步,启动并设置开机自启:
systemctl start zabbix-agent systemctl enable zabbix-agent第四步,Web 端添加主机。进入 Configuration -> Hosts -> Create host,填写 Host name(必须和 Agent 配置一致)、可见名称、所属主机组。然后在 Templates 标签页关联模板,Linux 服务器一般关联Template OS Linux。
第五步,等待数据上报。主动模式下,Agent 默认 120 秒刷新一次配置,所以新加的主机可能要等两分钟才有数据。想快点看到效果,可以重启一下 Agent 强制刷新。
第六步,验证数据。在 Monitoring -> Latest data 里筛选主机,看各个监控项是否有值。如果某个监控项一直没数据,先检查 Agent 日志/var/log/zabbix/zabbix_agentd.log,再看 Server 日志。
3.2 采集频率与历史数据保留的策略设计
采集频率不是越密越好,它直接决定了数据库的写入压力和存储增长。Zabbix 的存储分两类:历史数据(history)和趋势数据(trends)。历史数据保留原始值,趋势数据是每小时聚合的最小/最大/平均值。
我的经验配置是这样的:
| 指标类型 | 采集间隔 | 历史保留 | 趋势保留 |
|---|---|---|---|
| CPU/内存 | 60秒 | 7天 | 365天 |
| 磁盘空间 | 300秒 | 30天 | 365天 |
| 网络流量 | 60秒 | 7天 | 365天 |
| 进程状态 | 60秒 | 7天 | 90天 |
| 业务指标 | 300秒 | 90天 | 365天 |
这个配置的逻辑是:变化快的指标保留短一点,变化慢的保留长一点。CPU 每秒都在跳,存一年原始数据意义不大,看趋势就够了;磁盘空间变化慢,但排查问题时需要看历史,所以历史保留长一些。
存储估算的公式大致是:每日数据量 = 监控项数量 × (86400 / 采集间隔) × 每条记录字节数。Zabbix 每条历史记录大约 50 到 100 字节(取决于数据库和索引)。1000 个监控项、60 秒间隔,一天就是 144 万条记录,按 80 字节算约 115MB。这个量级用 MySQL 还能扛,再大就得上分区表或者 TimescaleDB 了。
3.3 批量部署时的自动化思路
手动一台台配 Agent 在规模上到几十台时就不可行了。我的做法是用配置管理工具批量推送,或者写个简单的 Shell 脚本配合 SSH 批量执行。
脚本的核心逻辑是:读取一个主机清单文件,逐台 SSH 过去,替换配置文件里的 Hostname,重启 Agent。
#!/bin/bash SERVER_IP="192.168.1.100" while read -r hostname ip; do ssh root@$ip "sed -i 's/^Hostname=.*/Hostname=$hostname/' /etc/zabbix/zabbix_agentd.conf" ssh root@$ip "sed -i 's/^Server=.*/Server=$SERVER_IP/' /etc/zabbix/zabbix_agentd.conf" ssh root@$ip "sed -i 's/^ServerActive=.*/ServerActive=$SERVER_IP/' /etc/zabbix/zabbix_agentd.conf" ssh root@$ip "systemctl restart zabbix-agent" echo "$hostname done" done < hostlist.txt主机清单文件格式:
app-server-01 192.168.1.11 app-server-02 192.168.1.12 db-server-01 192.168.1.21Web 端的主机添加也可以用 Zabbix API 批量做,比手工点快得多。API 调用示例:
import requests import json url = "http://192.168.1.100/zabbix/api_jsonrpc.php" headers = {"Content-Type": "application/json-rpc"} # 先登录拿 token login = { "jsonrpc": "2.0", "method": "user.login", "params": {"user": "Admin", "password": "zabbix"}, "id": 1 } token = requests.post(url, headers=headers, data=json.dumps(login)).json()["result"] # 创建主机 create_host = { "jsonrpc": "2.0", "method": "host.create", "params": { "host": "app-server-01", "interfaces": [{ "type": 1, "main": 1, "useip": 1, "ip": "192.168.1.11", "dns": "", "port": "10050" }], "groups": [{"groupid": "2"}], "templates": [{"templateid": "10001"}] }, "auth": token, "id": 2 } result = requests.post(url, headers=headers, data=json.dumps(create_host)).json() print(result)这套组合拳打下来,100 台主机的部署时间能从半天压缩到十几分钟。
4. 采集故障的排查思路与避坑实录
4.1 数据不上报的排查决策树
数据不上报是最常见的问题,排查要按层次来,不要一上来就瞎改配置。
先确认 Agent 进程活着:systemctl status zabbix-agent。进程挂了就看日志找原因,常见的是配置文件语法错误或者端口被占用。
进程活着但没数据,检查网络连通性。被动模式下从 Server 端telnet agent_ip 10050,主动模式下从 Agent 端telnet server_ip 10051。不通就是防火墙或者网络策略的问题。
网络通了还没数据,检查 Hostname 匹配。主动模式下这是最高频的故障原因。在 Agent 上执行zabbix_agentd -t system.hostname看实际主机名,和 Web 端对比。
最后检查监控项本身。在 Web 端用 "Test" 功能测试一下,或者从 Server 端用zabbix_get手动拉一次:
zabbix_get -s 192.168.1.11 -p 10050 -k "system.cpu.load[all,avg1]"有返回值说明采集通道没问题,问题在 Web 端配置;没返回值说明 Agent 端有问题。
4.2 常见问题速查表
| 现象 | 可能原因 | 排查方法 | 解决方式 |
|---|---|---|---|
| 主机显示红色不可达 | Agent 未启动或端口不通 | telnet 10050 端口 | 启动 Agent 或放行端口 |
| 主动模式无数据 | Hostname 不匹配 | 对比 Agent 和 Web 端主机名 | 改成完全一致 |
| 部分监控项无数据 | Key 写错或脚本报错 | zabbix_get 手动测试 | 修正 Key 或脚本 |
| 数据延迟很大 | 采集队列积压 | 看 Server 队列状态 | 增加 Poller 或降低频率 |
| SNMP 超时 | 设备响应慢或 community 错 | snmpwalk 手动测试 | 调大 timeout 或改配置 |
| JMX 连不上 | Java Gateway 未启动 | 检查 10052 端口 | 启动 Gateway |
| 数据有断点 | Agent 重启或网络抖动 | 看 Agent 日志 | 排查重启原因 |
4.3 几个我踩过的坑和独家经验
第一个坑是时区问题。Zabbix Server、数据库、Agent 三者的时区如果不一致,数据时间戳会错乱,图表上会出现数据"穿越"到未来或者过去的情况。我的做法是全部统一成 UTC,Web 端显示时再转本地时区。
第二个坑是主动模式的配置刷新延迟。新加的主机或者改了监控项,主动模式下要等RefreshActiveChecks设定的时间才生效。调试阶段我会临时把这个值改成 10 秒,调完再改回去。
第三个坑是 SNMP 的 OID 索引。采集多核 CPU 利用率时,OID 后面要带核的索引号,不同厂商的索引规则还不一样。有的从 0 开始,有的从 1 开始,有的用位图。这个只能靠 snmpwalk 实测确认。
第四个坑是自定义脚本的执行用户。Agent 默认以 zabbix 用户运行,如果脚本需要 root 权限(比如读某些系统文件),要么给脚本设 SUID,要么在 sudoers 里给 zabbix 用户免密权限。我一般选后者,更可控。
提示:自定义脚本一定要加超时控制。脚本卡死会拖垮整个 Agent 的采集队列。在脚本里用
timeout 10包一层,或者在 Agent 配置里设Timeout参数。
4.4 采集性能的监控与调优
采集系统本身也需要被监控。我一般会关注这几个指标:Zabbix Server 的队列积压数、Poller 进程的繁忙程度、数据库的写入延迟。
队列积压是最直接的信号。在 Web 端 Administration -> Queue 里能看到,如果某个类型的监控项积压持续增长,说明采集能力跟不上采集需求。解决办法有两个:增加对应的 Poller 数量,或者降低采集频率。
数据库写入延迟往往被忽略。Zabbix 的 history 表写入非常频繁,如果磁盘 IO 跟不上,数据会先在内存队列里堆积,最终导致丢数据。我的经验是给 Zabbix 数据库单独挂 SSD,或者至少把数据文件和日志文件分到不同磁盘。
Poller 数量的调整在 Server 配置里:
StartPollers=10 StartPollersUnreachable=5 StartTrappers=5 StartPingers=5StartPollers是通用轮询进程,StartPollersUnreachable专门处理不可达主机的重试,StartTrappers处理主动模式和 Trapper 数据,StartPingers处理 ICMP ping。这几个值要根据实际负载调,不是越大越好,进程太多反而增加上下文切换开销。
我一般的调优顺序是:先看队列积压类型,确定瓶颈在哪个环节,再针对性增加对应进程数,每次加 5 个,观察一段时间再决定是否继续加。盲目把所有值调大,只会让问题更难定位。
采集层的稳定性直接决定了整个监控体系的可信度。把这一层做扎实,后面的告警和可视化才有意义。我在实际项目中的体会是,花在采集调试上的时间,最终都会在故障排查时省回来。