关于本专栏
由民生银行潜望者Zabbix开源监控项目项目组投稿,为社区分享他们整理的Zabbix源码解析、民生银行潜望者Zabbix运维管理平台、多Server架构实现、容器/数据库/中间件全自动注册监控等项目文档。
本专栏将每季度发布2-3篇,持续更新,希望大家交流互动,一起讨论优化、提高!
Zabbix源码解析之Server启动流程
(Zabbix 4.0.8)
杜大为
民生银行潜望者Zabbix监控项目骨干成员,2016年开始使用Zabbix,在Zabbix多Server架构设计、自动化 监控方案设计实现、源码解析方面有丰富的经验。
概述
Zabbix Server是所有配置、统计和操作数据的中央存储中心,也是 Zabbix 监控系统的告警中心,负责执行数据的主动轮询和被动获取,计算触发器条件,向用户发送通知。
Server端进程有多达二十多种(当我们在操作系统下用ps –ef命令来查看时,往往看到很多zabbix系统进程,而这些系统进程在zabbix内部称为实例。这些实例各处负责不同的工作,就形成了不同种类型的进程)。
整体启动过程
Server启动后,会先读取配置文件,接受命令行参数,然后执行一系列的初始化动作,创建负责不同工作的进程实例后, Server开始运行工作,如下:
接下来我们一起分析并解读zabbix server端源代码,我们增加了注释和说明,有助于大家了解启动过程的具体实现。
main函数
源码文件server.c的main函数是zabbix server的程序入口,通过分析main函数执行过程,总结操作序列如下图所示:
struct ZBX_TASK_EX
该结构体用于zabbix启动时记录zabbix任务的一些信息。
• zbxtaskt: 是一个枚举,表示任务类型,在启动时指定为:ZBX_TASK_START。如果启动时指定 --runtime-control(或-R)选项(执行管理能力),则设置t.task = ZBX_TASK_RUNTIME_CONTROL。
• flags: 代表启动时的标志。如果启动时指定--foreground(或-f)选项(在前台运行zabbix守护进程),则t.flags会多添加一个ZBX_TASK_FLAG_FOREGROUND标志。当zabbix_server作为daemon启动时,flags会作为daemon的参数传入。
• data: 记录--runtime-control的选项信息,比如改变日志的级别或cache reload的值。比如:-R log_level_increase,-R config_cache_reload。
struct cfg_line
该结构体用于表示一个配置选项
• parameter: zabbix_server.conf中的参数名
• variable: 程序中参数的值
• type: 参数类型,有TYPEINT,TYPESTRING等类型
• mandatory: 是否是必须设定的参数
• min: 限定参数范围,最小值
• max: 限定参数范围,最大值
daemon_start函数
操作序列如下图所示:
zbx_set_common_signal_handlers函数
该函数用来设置通用的信号的handlers。
sigaction函数
POSIX标准定义的信号处理接口是sigaction函数,其接口头文件及原型如下:
• signum:要操作的信号。
• act:要设置的对信号的新处理方式。
• oldact:原来对信号的处理方式。
struct sigaction
该结构体用来描述对信号的处理。
• sa_handler: 函数指针,其含义是一个信号处理函数。只不过它只有一个int参数。
• sa_sigaction: 函数指针,另一个信号处理函数,它有三个参数,可以获得关于信号的更详细的信息。
• sa_mask: 用来指定在信号处理函数执行期间需要被屏蔽的信号,特别是当某个信号被处理时,它自身会被自动放入进程的信号掩码,因此在信号处理函数执行期间这个信号不会再度发生。
• sa_flags: 用于指定信号处理的行为,它可以是以下值的“按位或”组合。
– SA_RESTART: 使被信号打断的系统调用自动重新发起。
– SA_NOCLDSTO: 使父进程在它的子进程暂停或继续运行时不会收到 SIGCHLD 信号。
– SA_NOCLDWAIT: 使父进程在它的子进程退出时不会收到 SIGCHLD 信号,这时子进程如果退出也不会成为僵尸进程。
– SA_NODEFER:使对信号的屏蔽无效,即在信号处理函数执行期间仍能发出这个信号。
– SA_RESETHAND: 信号处理之后重新设置为默认的处理方式。
– SASIGINFO: 使用 sasigaction 成员而不是 sahandler 作为信号处理函数。包含了`SASIGINFO标志时,系统将使用sasigaction函数作为信号处理函数,否则使用sahandler作为信号处理函数。在某些系统中,成员sahandler与sasigaction`被放在联合体中,因此使用时不要同时设置。
set_daemon_signal_handlers函数
该函数用来设置daemon使用的信号的handlers。
zbx_set_child_signal_handler函数
该函数用来设置子进程的信号的handlers。
MAIN_ZABBIX_ENTRY函数
操作序列如下图所示:
zabbix_open_log函数
该函数用于打开日志文件
zbx_load_modules函数
加载可加载模块(动态链接库的形式,example中的dummy的例子)。
DBconnect函数
连接到数据库。
DCsync_configuration函数
从DB中同步配置数据
zbx_check_postinit_tasks函数
处理初始化以后的任务
DBclose函数
关闭数据库连接。
创建子进程
下面分析创建子进程的过程。
struct zbx_thread_args_t
该结构体保存进程参数
• server_num:进程编号
• process_num:此种类型的进程的序号
• processtype: 创建的子进程类型,如:ZBXPROCESSTYPEHOUSEKEEPER,ZBXPROCESSTYPE_POLLER
• args:进程的附加参数信息
ZBX_THREAD_ENTRY宏
定义宏的目的,是为了跨平台,统一使用一个名称。
ZBX_THREAD_ENTRY定义了函数,在创建新进程时,会调用这些函数
ZBX_THREAD_ENTRY(dbconfig_thread, args) ... ZBX_THREAD_ENTRY(poller_thread, args) ... ZBX_THREAD_ENTRY(trapper_thread, args) ...
创建各个子进程
zbx_thread_start函数
zbx_thread_start是一个封装函数,在其中会调用fork()函数,创建子进程。
zbx_on_exit函数
当子进程发生错误,导致主进程退出时,执行zbx_on_exit函数。
记录日志
配置文件中的配置
zabbixserver的日志的位置,级别等配置,在`zabbixserver.conf`中进行配置。
实现
1、zabbix日志的实现,头文件在:include/log.h,实现文件在src/libs/zbxlog/log.c中。
2、配置文件中的LogType指定日志文件的类型,一般记录到文本文件中,因此指定为file。对应的源码中的设置为:
3、当LogType指定为file时,需要LogFile指定记录的日志文件的名称和位置。
4、DebugLevel指定日志级别。默认为warnings。对应源码中的设置为:
5、无论日志级别设置为什么,使用LOG_LEVEL_INFORMATION级别来设置日志,总是能打印出来。所以我们在调查源码时,可以以LOG_LEVEL_INFORMATION级别来记录调试日志。