2 预处理详情

概述

本节提供监控项值预处理的详细信息。监控项值预处理允许为接收到的监控项值定义并执行转换规则

预处理由预处理管理器进程及执行预处理步骤的预处理工作进程共同管理。 所有带有预处理的值在由不同的数据采集器接收后,在被添加到历史缓存之前,都会先经过预处理管理器。 数据采集器(poller、trapper 等)与预处理进程之间使用基于套接字的 IPC 通信。 Zabbix 服务器或 Zabbix proxy(对于由 proxy 监控的监控项)会执行这些预处理步骤。

监控项值处理

为了直观展示从数据源到 Zabbix 数据库的数据流,我们可以使用下图这个简化示意图:

上图仅以简化形式展示了与监控项值处理相关的进程、对象和操作。图中未显示条件性方向变化、错误处理或循环。预处理管理器的本地数据缓存也未显示,因为它不会直接影响数据流。该图的目的是展示参与监控项值处理的各个进程及其交互方式。

  • 数据采集从数据源中的原始数据开始。此时,数据仅包含 ID、时间戳和值(也可以是多个值)。
  • 无论使用哪种类型的数据采集器,其基本思路都是相同的,适用于主动检查、被动检查、trapper 监控项等;变化的只是数据格式以及通信的发起方(即数据采集器等待连接和数据,或由数据采集器发起通信并请求数据)。原始数据会先经过验证,然后从配置缓存中获取监控项配置(即为数据补充配置数据)。
  • 基于套接字的 IPC 机制用于将数据从数据采集器传递到预处理管理器。此时,数据采集器会继续采集数据,而无需等待预处理管理器的响应。
  • 执行数据预处理。这包括执行预处理步骤以及依赖监控项处理。

如果任一预处理步骤失败,监控项在执行预处理期间可能会变为 NOT SUPPORTED 状态。

  • 预处理管理器本地数据缓存中的历史数据会被刷新到历史缓存中。
  • 此时,数据流会停止,直到下一次历史缓存同步(即 history syncer 进程执行数据同步时)。
  • 同步过程开始时,会先进行数据规范化,然后再将数据存储到 Zabbix 数据库中。数据规范化会将数据转换为所需的监控项类型(即监控项配置中定义的类型),其中包括根据这些类型允许的预定义大小对文本数据进行截断(字符串使用 HISTORY_STR_VALUE_LEN,文本使用 HISTORY_TEXT_VALUE_LEN,日志值使用 HISTORY_LOG_VALUE_LEN)。规范化完成后,数据将被发送到 Zabbix 数据库。

如果数据规范化失败,监控项可能会变为 NOT SUPPORTED 状态(例如,文本值无法转换为数字时)。

  • 采集到的数据会被进一步处理——检查触发器、在监控项变为 NOT SUPPORTED 时更新监控项配置等。
  • 从监控项值处理的角度来看,这就是数据流的终点。

监控项值预处理

数据预处理按以下步骤执行:

  • 如果监控项既没有预处理也没有依赖监控项,则其值会被添加到历史缓存中,或发送给 LLD 管理器。否则,监控项值会通过基于 UNIX socket 的 IPC 机制传递给预处理管理器。
  • 系统会创建一个预处理任务并将其添加到队列中,同时通知预处理 worker 有新任务。
  • 此时,数据流会停止,直到至少有一个未被占用的预处理 worker(即未执行任何任务)。
  • 当有可用的预处理 worker 时,它会从队列中获取下一个任务。
  • 预处理完成后(无论预处理步骤执行失败还是成功),预处理后的值都会被添加到已完成任务队列中,并通知管理器有新的已完成任务。
  • 预处理管理器会将结果转换为所需格式(由监控项值类型定义),并将其添加到历史缓存中或发送给 LLD 管理器。
  • 如果已处理的监控项存在依赖监控项,则会将依赖监控项连同预处理后的主监控项值一起添加到预处理队列中。依赖监控项会绕过常规的值预处理请求直接入队,但仅适用于已设置值且不处于 NOT SUPPORTED 状态的主监控项。

请注意,图中对主监控项预处理过程做了少许简化,省略了预处理缓存。

预处理队列

预处理队列组织如下:

  • 待处理任务列表:

    • 直接从值预处理请求中按接收顺序创建的任务
  • 立即任务列表(在待处理任务之前处理):

    • 测试任务(作为前端的监控项/预处理测试请求的响应而创建)
    • 依赖监控项任务
    • 顺序任务(必须按严格顺序执行的任务):
      • 具有使用最后一个值的预处理步骤的任务:
        • 更改
        • 节流
        • JavaScript(字节码缓存)
      • 依赖监控项预处理缓存
  • 已完成任务列表

预处理缓存

预处理缓存被引入,以改善具有相似预处理步骤的多个依赖监控项(这是常见的LLD结果)的预处理性能。

通过对一个依赖监控项进行预处理,并重用一些内部预处理数据,来为其余的依赖监控项提供缓存。预处理缓存仅支持以下类型的第一个预处理步骤:

  • Prometheus 模式(按度量衡输入的索引)
  • JSONPath(将数据解析为对象树,并索引第一个表达式 [?(@.path == "value")]

预处理 worker

Zabbix 服务器配置文件允许用户设置预处理 worker 线程的数量。 应使用 StartPreprocessors 配置参数来设置预先启动的预处理 worker 实例数量,该数量至少应与可用的 CPU 核心数相匹配。

如果预处理任务不是 CPU 密集型的,并且涉及频繁的网络请求,建议配置更多的 worker。 预处理 worker 的最佳数量可由多种因素决定,包括“可预处理”监控项(即需要执行任意预处理步骤的监控项)的数量、数据采集进程的数量、监控项预处理的平均步骤数等。 worker 数量不足可能导致较高的内存使用量。有关排查 Zabbix 安装中过高内存使用量的方法,请参见 使用 tcmalloc 分析过高的内存使用量

但是,假设不存在诸如解析大型 XML/JSON 数据块之类的高负载预处理操作,则预处理 worker 的数量可以与数据采集器的总数相匹配。这样一来,大多数情况下(数据由采集器批量送达的情况除外),对于已采集的数据,至少都会有一个空闲的预处理 worker 可用。

过多的数据采集进程(poller、unreachable poller、ODBC poller、HTTP poller、Java poller、pinger、trapper、proxypoller)以及 IPMI manager、SNMP trapper 和预处理 worker,可能会耗尽预处理 manager 的每进程文件描述符限制。

每进程文件描述符限制耗尽将导致 Zabbix 服务器停止运行,通常会在启动后不久发生,但有时也可能需要更长时间。 为避免此类问题,请检查 Zabbix 服务器配置文件,以优化并发检查数和进程数。 此外,如有必要,请通过检查并调整系统限制,确保文件描述符限制设置得足够高。

值处理管道

监控项值处理由多个进程分多个步骤(或阶段)执行。这可能导致:

  • 依赖监控项可以接收到值,而主监控项却不能。 这可以通过以下用例实现:
    • 主监控项的值类型为 UINT(可使用 trapper 监控项), 依赖监控项的值类型为 TEXT
    • 主监控项和依赖监控项都不需要任何预处理步骤。
    • 应将文本值(例如 "abc")传递给主监控项。
    • 由于没有需要执行的预处理步骤,预处理管理器会检查主监控项是否不处于 NOT SUPPORTED 状态以及值是否已设置(两者都为真),然后将依赖监控项以与主监控项相同的值加入队列(因为没有预处理步骤)。
    • 当主监控项和依赖监控项都进入历史同步阶段时,主监控项会因值转换错误而变为 NOT SUPPORTED 状态(文本数据无法转换为无符号整数)。

因此,依赖监控项会接收到一个值,而主监控项则会将其状态更改为 NOT SUPPORTED。

  • 依赖监控项接收到的值在主监控项历史记录中不存在。该用例与前一个非常相似,区别仅在于主监控项类型。例如,如果主监控项使用 CHAR 类型,那么主监控项的值会在历史同步阶段被截断,而依赖监控项将从主监控项的初始值(未截断的值)中接收其值。