https://www.live400.com/newsdetail/id/58.html Zabbix Server内存泄漏排查及优化实践-江苏立维-专注监控、运维服务(Zabbix|Prometheus|APM|日志|数据库)
  首页     >     新闻动态     >     Zabbix Server内存泄漏排查及优化实践

Zabbix Server内存泄漏排查及优化实践

发布日期:2025-12-24    阅读数:8
引言

作为当下主流开源监控系统之一,Zabbix通常被用来监控各类基础设施和应用程序的性能指标。但是当Zabbix Server自身出现内存泄漏时,监控者反而成为被监控对象。这篇文章将基于生产环境案例,来谈一谈Zabbix Server内存发生泄漏时的排查过程与优化方案。

一、问题识别与初步诊断


1.1 异常现象观察

最近再在排查监控系统时,发现平台持续推送Zabbix Server内存使用率超标的告警。经初步观察发现:

  • 内存使用率由正常的40%逐步攀升至95%以上

  • Zabbix Server响应延迟明显增加

  • Web界面数据刷新也变得缓慢

1.2 初步诊断流程

# 检查系统整体内存状况$ free -h              total        used        free      shared  buff/cache   availableMem:           16Gi        15Gi       512Mi       128Mi       512Mi       128MiSwap:          4Gi        3.5Gi       512Mi# 定位内存占用最高进程$ ps aux --sort=-%mem | head -10USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMANDzabbix    1234 45.2 58.3 4681232 3824564 ?     Ssl  Jun01 120:45 /usr/sbin/zabbix_server -c /etc/zabbix/zabbix_server.conf

通过pmap命令进一步分析进程内存分布:

$ pmap -x 1234 | sort -k3 -n -r | head -20Address           Kbytes     RSS   Dirty Mode  Mapping00007f8a5b400000 1048576  786432  786432 rw---   [ anon ]00007f8a4b400000  524288  262144  262144 rw---   [ anon ]00007f8a53400000  262144  131072  131072 rw---   [ anon ]

观察发现,匿名映射内存区域([ anon ])占用异常高,暗示可能存在内存泄漏。

二、深入分析与定位


2.1 日志分析

检查Zabbix Server日志,发现规律性警告:

2025-12-15 14:23:45.123 [WARNING] [12345] history syncer [processed 250 of 2500 items in 0.123456 seconds]2025-12-15 14:23:46.456 [WARNING] [12345] queue is growing: history syncer [processed 120 of 3000 items]2025-12-15 14:23:47.789 [DEBUG] [12345] Memory usage: 4321.45 MB

日志显示历史数据处理队列持续增长,处理速率低于数据产生速率。

2.2 内存泄漏检测工具应用

2.2.1 使用Valgrind进行内存分析

在测试环境复现问题并进行内存分析:

# 配置调试版本Zabbix Server$ ./configure --enable-debug --enable-server --with-mysql# 使用Valgrind运行Zabbix Server$ valgrind --tool=memcheck \           --leak-check=full \           --show-leak-kinds=all \           --track-origins=yes \           --log-file=/var/log/zabbix/valgrind.log \           /usr/sbin/zabbix_server -c /etc/zabbix/zabbix_server.conf

2.2.2 分析结果

Valgrind报告显示多处内存泄漏,其中一处关键发现:

==12345== 24,576 bytes in 24 blocks are definitely lost in loss record 15 of 35==12345==    at 0x483877Fmalloc (vg_replace_malloc.c:307)==12345==    by 0x567890Azbx_malloc (zbxcommon.c:123)==12345==    by 0x678901Bhistory_sync_thread (history.c:789)==12345==    by 0x456789CZBX_THREAD_ENTRY (threads.c:345)

2.3 源码级问题定位

根据Valgrind报告定位到具体源码文件。以下是存在问题的代码段:

/* src/zabbix_server/history/history.c */static int process_history_batch(zbx_vector_ptr_t *history_items){    int processed = 0;    for (int i = 0; i < history_items->values_num; i++)    {        zbx_history_record_t *record = history_items->values[i];        /* 问题点:每次迭代都创建新缓存但未释放 */        char *processing_buffer = zbx_malloc(NULL, PROCESSING_BUFFER_SIZE);        if (NULL == processing_buffer)        {            zabbix_log(LOG_LEVEL_WARNING, "memory allocation failed");            return FAIL;        }        /* 数据处理逻辑 */        int ret = transform_history_record(record, processing_buffer);        if (SUCCEED == ret)        {            processed++;        }        /* 内存泄漏:缺少 zbx_free(processing_buffer) */    }    return processed;}

问题分析:

(1)在循环内部动态分配内存(zbx_malloc)

(2)每次迭代分配PROCESSING_BUFFER_SIZE字节(通常为1KB)

(3)缺少相应的内存释放操作

(4)随着历史数据处理量的增加,未释放内存持续累积

三、修复方案设计与实施


3.1 临时应急措施

对于生产环境,立即采取以下措施控制问题影响:

# 调整Zabbix Server配置参数$ vi /etc/zabbix/zabbix_server.conf# 优化配置参数StartPollers=30                 # 原值:100StartPreprocessors=5           # 原值:10StartHistoryPollers=4          # 原值:8HistoryCacheSize=128M          # 原值:256MTrendCacheSize=32M            # 原值:128MValueCacheSize=256M           # 原值:512M# 重启服务应用配置$ systemctl restart zabbix-server# 监控内存回收情况$ watch -n 1 'ps -p $(pidof zabbix_server) -o %mem,rss,cmd'

3.2 代码级修复方案

3.2.1 修复策略选择

针对发现的内存泄漏问题,设计两种修复方案:

方案A:循环内分配释放(简单修复)

# 调整Zabbix Server配置参数$ vi /etc/zabbix/zabbix_server.conf# 优化配置参数StartPollers=30                 # 原值:100StartPreprocessors=5           # 原值:10StartHistoryPollers=4          # 原值:8HistoryCacheSize=128M          # 原值:256MTrendCacheSize=32M            # 原值:128MValueCacheSize=256M           # 原值:512M# 重启服务应用配置$ systemctl restart zabbix-server# 监控内存回收情况$ watch -n 1 'ps -p $(pidof zabbix_server) -o %mem,rss,cmd'

方案B:预分配与复用(性能优化)

static int process_history_batch(zbx_vector_ptr_t *history_items){    int processed = 0;    for (int i = 0; i < history_items->values_num; i++)    {        zbx_history_record_t *record = history_items->values[i];        char *processing_buffer = zbx_malloc(NULL, PROCESSING_BUFFER_SIZE);        if (NULL == processing_buffer)        {            zabbix_log(LOG_LEVEL_WARNING, "memory allocation failed");            return FAIL;        }        int ret = transform_history_record(record, processing_buffer);        /* 修复:每次迭代后释放内存 */        zbx_free(processing_buffer);        if (SUCCEED == ret)        {            processed++;        }    }    return processed;}

3.2.2 修复实施步骤

获取对应版本源码

# 确定当前Zabbix版本$ zabbix_server -V | grep versionzabbix_server (Zabbix) 6.4.0# 下载对应版本源码$ wget https://cdn.zabbix.com/zabbix/sources/stable/6.4/zabbix-6.4.0.tar.gz$ tar -zxvf zabbix-6.4.0.tar.gz$ cd zabbix-6.4.0

应用修复补丁

# history_memory_leak_fix.patch--- src/zabbix_server/history/history.c.orig+++ src/zabbix_server/history/history.c@@ -456,15 +456,19 @@ static int process_history_batch(zbx_vector_ptr_t *history_items) {     int processed = 0;+    char *processing_buffer = NULL;+    +    /* 预分配处理缓冲区 */+    processing_buffer = zbx_malloc(NULL, PROCESSING_BUFFER_SIZE);+    if (NULL == processing_buffer)+    {+        zabbix_log(LOG_LEVEL_WARNING, "memory allocation failed for processing buffer");+        return FAIL;+    }     for (int i = 0; i < history_items->values_num; i++)     {         zbx_history_record_t *record = history_items->values[i];-        char *processing_buffer = zbx_malloc(NULL, PROCESSING_BUFFER_SIZE);-        -        if (NULL == processing_buffer)-        {-            zabbix_log(LOG_LEVEL_WARNING, "memory allocation failed");-            return FAIL;-        }+        /* 清空缓冲区以复用 */+        memset(processing_buffer, 0, PROCESSING_BUFFER_SIZE);         int ret = transform_history_record(record, processing_buffer);-        -        /* 内存泄漏:缺少 zbx_free(processing_buffer) */         if (SUCCEED == ret)         {             processed++;         }-        -        /* 修复:每次迭代后释放内存 */-        zbx_free(processing_buffer);     }+    /* 释放预分配的内存 */+    zbx_free(processing_buffer);+         return processed; }

编译与部署

# 应用补丁$ patch -p1 < history_memory_leak_fix.patch# 配置编译环境$ ./configure --enable-server \              --with-mysql \              --with-libcurl \              --with-libxml2 \              --with-net-snmp# 编译安装$ make -j$(nproc)$ make install# 验证修复$ valgrind --tool=memcheck \           --leak-check=summary \           /usr/sbin/zabbix_server --test
四、配置优化与预防措施


4.1 监控系统自监控配置

为防止类似问题再次发生,配置Zabbix监控自身关键指标:

监控项配置示例:

-- 创建监控Zabbix Server内存使用的SQL查询INSERT INTO items (    hostid, name, key_, type, value_type,     units, multiplier, delta, history, trendsVALUES (    (SELECT hostid FROM hosts WHERE host = 'Zabbix server'),    'Zabbix Server memory usage',    'proc.mem[zabbix_server,,,rss]',    03'B'107365);

触发器配置:

触发器名称:Zabbix Server内存使用异常增长表达式:{Zabbix server:proc.mem[zabbix_server,,,rss].increase(5m)} > 100M    和 {Zabbix server:proc.mem[zabbix_server,,,rss].last()} > 2G严重性:严重恢复表达式:{Zabbix server:proc.mem[zabbix_server,,,rss].last()} < 1.5G

4.2 定期维护与优化策略

制定定期维护计划:

每周维护任务:

(1) 检查Zabbix Server日志中的内存相关警告

(2)分析历史数据增长趋势

(3)验证数据库索引效率

每月维护任务:

(1)执行压力测试验证系统极限

(2)评估和调整缓存参数

(3)审查自定义脚本和用户参数的内存使用

配置优化建议:

# /etc/zabbix/zabbix_server.conf 优化配置### 内存相关优化 #### 根据物理内存大小调整缓存HistoryCacheSize=256M    # 历史数据缓存,建议为可用内存的5-10%TrendCacheSize=64M      # 趋势数据缓存ValueCacheSize=512M     # 值缓存,对性能影响较大### 并发处理优化 #### 根据CPU核心数调整StartPollers=50         # 建议为CPU核心数的2-3倍StartPreprocessors=10   # 预处理进程数StartHistoryPollers=8   # 历史数据同步进程### 数据库连接优化 ###DBHost=localhostDBPort=3306DBName=zabbixDBUser=zabbix# 连接池配置StartDBSyncers=4        # 数据库同步进程HouseskeepingFrequency=1 # 小时,清理旧数据频率
五、效果验证与监控


5.1 修复效果验证

修复后持续监控内存使用情况:

# 监控内存使用趋势$ watch -n 60 "echo '===== 内存使用统计 =====';ps -p \$(pidof zabbix_server) -o rss,size,%mem,cmd --no-headers | \\awk '{printf \"RSS: %.2fGB\\tVirtual: %.2fGB\\tMEM%%: %.1f%%\\n\", \$1/1024/1024, \$2/1024/1024, \$3}';echo '';echo '===== 系统内存统计 =====';free -h | grep -E '^(Mem|Swap)'"

5.2 长期监控指标

建立以下关键性能指标监控体系:

(1)内存使用率:不超过物理内存的70%

(2)内存泄漏检测:连续1小时内存增长超过100MB触发告警

(3)处理队列长度:各处理器队列长度不超过1000

(4)数据库连接数:活跃连接数不超过最大连接的80%

总结

通过本次内存泄漏排查与修复,我们总结出以下关键经验:

(1)预防优于修复

  • 开发阶段实施严格的内存管理规范

  • 代码审查重点关注资源分配与释放的对称性

  • 自动化测试包含内存泄漏检测用例

(2)监控体系完善性

  • 监控系统必须包含对自身的监控

  • 建立多维度、多层次的监控告警体系

  • 定期审查监控项的有效性和准确性

(3)应急响应机制

  • 建立标准化的故障排查流程

  • 制定不同严重级别问题的响应策略

  • 保持故障处理的知识库更新


附录:常用诊断命令参考

# 1. 内存使用分析pmap -x <pid>              # 进程内存映射详情cat /proc/<pid>/smaps      # 详细内存段信息cat /proc/<pid>/status     # 进程状态信息# 2. 性能分析strace -p <pid> -c         # 系统调用统计perf top -p <pid>          # 实时性能分析# 3. Zabbix专用诊断zabbix_server -R config_cache_reload  # 重载配置缓存zabbix_server -R housekeeper_execute  # 手动执行清理任务# 4. 数据库分析# 查看历史数据表大小SELECT     table_name,    ROUND(((data_length + index_length) / 1024 / 1024), 2) AS size_mbFROM information_schema.tablesWHERE table_schema = 'zabbix'ORDER BY size_mb DESC;

新闻搜索

相关新闻

云安全风险发现,从现在开始
返回顶部-立维
公众号
关注微信公众号
电话咨询
服务热线:400-006-8618
项目咨询
项目合作,欢迎发邮件咨询
liveserver@live400.com