Zabbix Agent / Agent 2 采集原理与运行机制详解
引言
Zabbix Agent 与 Agent2 是 Zabbix 监控体系中最核心的数据采集组件。当你在服务器上安装并启动 Agent 后,它便成为一个驻留系统中的守护进程,持续对外提供数据采集服务。
两代 Agent 的核心本质是 「本地系统接口读取器 + Zabbix 协议通信端」:它本身不生成监控数据,所有指标均来自操作系统内核暴露的标准接口;Agent 负责封装读取逻辑、按约定协议与 Server 交互,最终将系统指标传递给监控平台。两代 Agent 的数据来源完全一致,差异在于内部并发架构、组织方式与扩展能力。
一、数据的根本来源:操作系统原生接口
不管 Agent 1 还是 Agent 2,安装并启动后,它的核心工作可以概括为三步:
- 启动并监听:Agent 进程启动后,在本地监听 TCP 10050 端口(被动模式用),同时主动连接 Server/Proxy 的 10051 端口(主动模式用)。
- 接收或获取监控项列表:Agent 需要知道"采集什么"。这个"什么"就是监控项(Item),每个监控项有一个唯一的 Key(如
system.cpu.util、vm.memory.size[available])。 - 按 Key 执行采集动作并返回数据:Agent 根据 Key 找到对应的采集方式(系统调用、读文件、执行命令等),拿到原始值,返回给 Server。
1.1 主流系统的数据接口
| 平台 | 数据接口 | 说明 |
|---|---|---|
| Linux | /proc 虚拟文件系统、/sys 设备文件系统、系统调用(getloadavg()、statfs()、sysinfo() 等) |
内核态数据暴露的标准接口,无需特殊权限,是系统原生的暴露能力。 |
| Windows | PDH 性能计数器、Windows Native API、WMI 接口读取系统运行指标 | 通过性能计数器获取系统运行指标 |
| 其他 Unix/BSD | 各自对应的系统调用与内核接口 | 平台特定的接口实现 |
1.2 典型指标与底层来源对应
所有内建监控项(key)本质上就是把这些读取逻辑用代码封装好,调用时直接返回解析后的值:
| 监控项示例 | 底层数据来源(Linux) |
|---|---|
system.cpu.load |
读取 /proc/loadavg 文件 |
system.cpu.util |
读取 /proc/stat 文件,通过时间片差值计算使用率 |
vm.memory.size |
读取 /proc/meminfo 文件 |
net.if.in / net.if.out |
读取 /proc/net/dev 文件 |
vfs.fs.size |
调用 statfs() 系统调用读取文件系统元数据 |
proc.num |
遍历 /proc 下的进程目录统计数量 |
system.uptime |
读取 /proc/uptime 文件 |
system.hostname |
调用 gethostname() 系统调用 |
二、Zabbix Agent 1(C 语言版)架构与运行机制
传统 Agent 1 采用预派生多进程架构,安装后以系统服务运行,通过多进程分工完成监听、采集、上报全流程。
Agent 1 内部硬编码了一批内置监控项的实现逻辑。每个 Key 对应一段 C 代码,执行时通过以下方式获取数据:
| 采集方式 | 原理 | 典型 Key 示例 |
|---|---|---|
| 系统调用(syscall) | 直接调用操作系统内核提供的 API 获取信息,效率最高 | system.cpu.util(读取 /proc/stat 并计算差值) |
| 读取系统文件 | 读取 /proc、/sys 等虚拟文件系统中的文件 |
vm.memory.size[available](读取 /proc/meminfo) |
| 执行外部命令 | fork 子进程执行 Shell 命令或脚本 | UserParameter 定义的自定义监控项 |
2.1 启动与初始化流程
- 服务启动后,主进程(
agent #0)首先读取zabbix_agentd.conf配置文件,校验参数、初始化资源。 - 按配置 fork 出功能独立的子进程:
- 多个
listener进程:数量由StartAgents参数控制(默认 3 个),负责被动模式请求处理。 - 1 个
collector预采集进程:固定数量,不可配置,全局负责基础指标预采集与缓存。 - 1 个
active checks主动检查进程:固定数量,不可配置,负责主动模式全链路逻辑。
- 多个
- 各子进程独立运行,主进程监控子进程状态,异常退出时自动重启。
2.2 核心子进程职责
- 主进程:管理子进程生命周期,监控运行状态,异常时自动重启。
- listener 进程:被动模式专属,常驻监听 10050/TCP 端口,接收并处理 Server 发起的采集请求,多个进程并行处理。
- collector 进程:全局共享的预采集缓存进程,后台常驻以高频周期预采集 CPU、磁盘等常用基础指标并缓存结果;被动请求和主动采集均可直接复用缓存,降低系统调用开销,提升响应速度。
- active checks 进程:主动模式专属,全链路负责配置拉取、本地采集调度、缓冲区管理、批量上报。
2.3 被动模式采集运行机制
被动模式是 Server 主动拉取、Agent 被动响应的经典采集方式,调度权完全在 Server 侧。
- 监听等待:多个
listener进程常驻监听 10050/TCP 端口,等待 Server 端发起连接。 - 请求接收:Server 端
agent poller进程发起连接,发送监控项 Key 字符串。 - 解析执行:
listener解析 Key 与参数,匹配对应内建采集函数;若为 UserParameter 则 fork 子进程执行外部命令。 - 结果返回:采集完成后按 Zabbix 文本协议封装结果,返回给 Server,单次交互完成。
- 并发控制:并发能力由
StartAgents决定,超出数量的连接会进入队列等待。
Server/Proxy Agent (10050端口)
| |
|--- TCP连接,发送请求: "system.cpu.load[all,avg1]" -->|
| |--- 解析Key → 执行采集(读/proc/loadavg)
|<--- 返回结果: "0.15 0.10 0.08" ----------------|
|--- 关闭连接 |
2.4 主动模式采集运行机制
主动模式下采集调度权下沉至 Agent 侧,Agent 自主完成配置拉取、本地采集与批量上报。
- 配置拉取:
active checks进程按RefreshActiveChecks周期(默认 120 秒;Zabbix 6.4 起支持增量同步,默认 5 秒)主动连接 Server 10051 端口,携带主机名拉取主动监控项列表。 - 本地调度:在本地为每个监控项维护独立定时器,按配置间隔定时执行采集,可复用 collector 进程的预采集缓存。
- 缓冲批量:采集结果先写入内存缓冲区,达到
BufferSize数量阈值或BufferSend时间阈值时,批量打包上报。 - 断网容错:网络中断时数据暂存内存缓冲区,恢复后自动补传;进程重启后缓存数据丢失。
Agent Server/Proxy (10051端口)
| |
|--- TCP连接,发送: "我是host-A,给我监控项列表" -->|
|<--- 返回: [{key:system.cpu.util, delay:60s}, ...] --|
|--- 关闭连接(配置同步完成) |
| |
| [本地按间隔调度采集,复用collector缓存]
| [数据写入内存缓冲区]
| [达到阈值时批量上报]
|--- TCP连接,发送: "批量采集数据" ---->|
|<--- 返回: "success" --------------------|
三、Zabbix Agent 2(Go 语言版)架构与运行机制
Agent 2 是官方重构版本,核心采集逻辑不变,架构从「多进程」改为单进程 + 插件化协程,扩展性与性能更优。
3.1 启动与初始化流程
- 服务启动后,仅运行单个
zabbix_agent2主进程,读取zabbix_agent2.conf配置。 - 内部通过 Goroutine 协程启动多个功能模块:被动监听协程、主动检查协程、插件管理器、各采集插件协程。
- 所有模块在同一进程内并发运行,通过协程调度实现多任务,
ps命令只能看到一个主进程。
3.2 插件化采集体系
Agent 2 的核心变化是所有采集能力插件化,官方内置系统、日志、文件、网络、Docker、Systemd、数据库等十几种采集插件,第三方也可开发自定义插件。
内置插件示例:
| 插件 | 采集对象 | 数据来源 |
|---|---|---|
| CPU 插件 | CPU 使用率、负载 | /proc/stat、/proc/loadavg |
| 内存插件 | 内存使用情况 | /proc/meminfo、/proc/vmstat |
| 磁盘插件 | 磁盘 I/O、容量 | /proc/diskstats、/proc/mounts、statfs() |
| 网络插件 | 网络流量 | /proc/net/dev |
| Docker 插件 | 容器状态 | Docker API(Unix Socket) |
| Systemd 插件 | 服务状态 | systemd D-Bus 接口 |
| MySQL/Redis 等插件 | 数据库/中间件状态 | 对应服务的协议或 API |
插件接口:
| 接口 | 作用 |
|---|---|
| Exporter | 核心接口,定义 Export() 方法,负责执行采集并返回数据 |
| Configurator | 可选接口,定义 Configure() 方法,用于接收 Agent 传来的配置 |
| Runner | 可选接口,定义 Start()/Stop() 方法,用于需要长期运行的采集任务(如持续监听日志) |
Agent 2 通过 UNIX Socket(Linux)或 Named Pipe(Windows)与外部插件进行双向通信:
Agent 2 主进程
|
|--- UNIX Socket ---> 插件A(如 Docker 插件)
|--- UNIX Socket ---> 插件B(如 MySQL 插件)
|--- UNIX Socket ---> 插件C(自定义插件)
并发控制:
每个插件有独立的 Capacity 参数(默认 100),限制该插件最大并发执行的采集任务数。可通过 Plugins.<PluginName>.Capacity=N 配置调整。不同插件的检查可以并行执行,互不影响。
3.3 被动模式采集运行机制
- 监听协程常驻 10050 端口,接收 Server 连接请求。
- 为每个连接创建一个 goroutine 独立处理,并发能力由 Go runtime 自动调度,不受固定进程数限制。
- 解析 key 后,分发到对应采集插件。
- 插件内部调用系统接口或执行脚本,完成数据采集。
- 按 Zabbix 协议封装结果,返回给 Server。
3.4 主动模式采集运行机制
- 配置拉取:主动检查协程定期连接 Server 拉取监控配置。Zabbix 6.4 起支持增量同步,仅传输变更部分。
- 插件调度:配置分发给各采集插件,插件内部维护采集定时器,按各自的更新间隔执行采集。
- 缓冲上报:采集结果汇总到全局缓冲区,达到阈值后批量上报。
- 持久化缓存:支持
EnablePersistentBuffer参数,网络长时间中断时数据写入本地磁盘文件,进程重启也不丢失,恢复后自动补传。
四、两类监控项的具体采集原理
两代 Agent 通用,监控项分为内建指标与自定义参数两类,实现机制与性能差异显著。
4.1 内建 Key(内置指标)
-
原理:由 Agent 原生代码直接封装系统调用与内核接口读取逻辑,编译进二进制可执行文件。
-
执行流程:
收到 Key 请求 → 匹配内置处理函数 → 调用系统接口/读取内核文件 → 解析数值、格式化 → 返回结果 -
特点:纯内存/文件级操作,无额外进程开销,毫秒级响应,性能极高,是监控体系的核心主力。
-
限制:仅支持官方预设的系统级指标,无法自定义业务逻辑。
4.2 UserParameter(自定义参数)
-
原理:用户自定义外部命令或脚本,Agent 收到请求时创建子进程(Agent 1)或启动协程(Agent 2)执行命令,捕获标准输出作为监控值。
-
配置示例:
UserParameter=mysql.ping,mysqladmin -uroot ping | grep -c alive -
执行流程:
收到自定义 Key → 匹配配置中的命令模板 → 替换参数 → 创建执行环境运行命令 → 捕获 stdout 输出 → 去除首尾空白 → 返回结果 -
关键规则:
- 外部命令通过 shell(默认
/bin/sh)执行,存在进程创建、shell 解析等资源开销。 - 执行超时由
Timeout参数控制(默认 3 秒),超时强制终止,避免资源泄漏。 - 命令输出多行时,Agent 仅返回第一行作为结果。
- 外部命令通过 shell(默认
-
特点:灵活度极高,可实现任意业务指标;但性能开销远大于内建 Key,大量慢执行脚本会拖慢整体采集能力,需合理控制数量与耗时。
4.3 日志监控(log/logrt)
日志监控是特殊的采集类型,核心原理是跟踪文件新增内容,Agent 内部为每个日志项维护文件偏移量,确保不重复、不遗漏。
- 被动模式:Server 每次请求时,Agent 读取自上次偏移量后的新增内容,并更新偏移位置。
- 主动模式:Agent 本地自行跟踪文件变化,将新增行批量推送给 Server,效率更高;Agent 2 的
Runner接口插件尤其适合此类长期运行的采集任务。
五、端到端完整采集流程示例
示例 1:被动模式下 CPU 负载采集全流程
Server agent poller 按调度时间,向目标 Agent 10050 端口发起 TCP 连接
↓
发送请求字符串:system.cpu.load[all,avg1]
↓
Agent listener 进程(Agent 1)/协程(Agent 2)接收请求
↓
匹配内建 CPU 负载处理函数
↓
读取 /proc/loadavg 文件,解析出 1 分钟平均负载
↓
按 Zabbix 文本协议封装结果,返回给 Server
↓
Server 收到数据,进入预处理、缓存、触发器计算等后续流水线
示例 2:主动模式下内存使用率采集全流程
Agent 启动后,主动检查协程连接 Server 10051 端口,携带主机名拉取主动监控项列表
↓
拿到配置后,本地为 vm.memory.size 设置 60 秒采集定时器
↓
定时触发后,内存插件读取 /proc/meminfo,计算使用率,结果写入缓冲区
↓
缓冲区累计到阈值或达到最大保留时间时,批量打包发送给 Server
↓
Server trapper 进程接收数据,解析匹配后进入处理链路
六、两代 Agent 核心差异对比表
| 对比维度 | Agent 1(zabbix_agentd) | Agent 2(zabbix_agent2) |
|---|---|---|
| 开发语言 | C 语言 | Go 语言 |
| 进程模型 | 预派生多进程(fork) | 单进程 + 多协程(Goroutine) |
| 进程可见性 | 可通过 ps 查看主进程、listener、collector、active checks 等独立子进程 |
仅可见单一主进程,内部并发不可见 |
| 被动并发控制 | 全局 StartAgents 参数控制 listener 进程数 |
插件级 Capacity 参数分别控制各插件并发数 |
| 主动模式实现 | active checks 进程统一负责调度、采集与上报,共享 collector 预采集缓存 | 主动检查协程调度 + 各插件独立定时器采集 |
| 扩展方式 | 仅支持 UserParameter 外部脚本 | 原生插件体系 + UserParameter 兼容,支持第三方插件 |
| 配置同步 | 全量拉取 | 支持增量同步 |
| 持久化缓存 | 不支持,仅内存缓存,进程重启丢失 | 支持 EnablePersistentBuffer,数据可落盘持久化 |
| 内置采集能力 | 基础系统指标 | 基础指标 + Docker/Systemd/数据库等扩展插件 |
| 资源开销 | 多进程内存占用稍高,上下文切换开销大 | 单进程内存管理更高效,协程切换开销低 |
| 官方定位 | 兼容旧环境,轻量基础采集 | 新一代推荐版本,插件化、高并发、高扩展 |
七、总结
-
Agent 是一个守护进程:它按照 Server 下发的监控项列表,在本地执行对应的采集动作,然后把结果返回。Agent 本身不存储数据、不判断告警、不做预处理,这些全部由 Server 完成。
-
数据源头是操作系统内核接口:两代 Agent 采集数据的本质完全相同,都是读取
/proc、/sys、系统调用等内核暴露的标准接口,而非 Agent 自身生成数据。 -
内置监控项:Agent 内部硬编码了读取操作系统指标的逻辑(读
/proc、调系统 API),每个 Key 对应一段采集代码。⭐ -
UserParameter:管理员通过配置 Shell 命令,让 Agent 执行自定义命令获取数据。⭐
-
日志监控基于文件偏移跟踪:Agent 记住上次读取位置,只采集新增内容,主动模式对此有原生优化。
-
Agent 1 靠多进程实现并发,架构经典、资源隔离好;Agent 2 靠协程 + 插件实现并发,扩展性更强、性能更优、功能更丰富。
-
Agent 2 插件:通过 Go 插件机制,将采集逻辑模块化、并发化,效率更高。

浙公网安备 33010602011771号