说明:Zabbix 官方 Docker 镜像支持用
ZBX_*环境变量直接映射到zabbix_server.conf的同名参数(例如ZBX_LOGSLOWQUERIES对应LogSlowQueries),以及DB_SERVER_HOST/MYSQL_*等数据库连接变量。
参数含义/原理可查 Zabbix 官方 server 配置文档。

一、服务端优化点
A. 抗高并发采集:进程数(poller / preprocess / trapper / dbsyncer)
StartPollers / StartPollersUnreachable / StartPingers / StartHTTPPollers:决定并发采集能力(队列堆积、
busy%高就要加)StartPreprocessors:预处理并发(依赖 item preprocessing、LLD、复杂表达式时很关键)
StartDBSyncers:写库并发(历史写入慢、DB 压力大时关键)
这些都能用镜像环境变量直接配:ZBX_STARTPOLLERS、ZBX_STARTPREPROCESSORS、ZBX_STARTDBSYNCERS 等。
B. 抗“缓存不足/频繁读库”:Cache / HistoryCache / TrendCache / ValueCache
核心逻辑:Zabbix server 是强缓存架构,缓存小会导致:
配置缓存频繁抖动、触发器/计算慢
历史写入/读取卡顿
前端“忙”、队列堆积
对应可配项(Docker env 支持):ZBX_CACHESIZE / ZBX_HISTORYCACHESIZE / ZBX_HISTORYINDEXCACHESIZE / ZBX_TRENDCACHESIZE / ZBX_VALUECACHESIZE
C. Housekeeping(保洁)不要“把库拖死”
HousekeepingFrequency/MaxHousekeeperDelete:如果历史量大,housekeeping 会制造巨大 delete 压力(MySQL 最怕)常见实践:降低每轮删除量、避免频繁全表大清理(并结合分区/保留策略)
Docker env 支持:ZBX_HOUSEKEEPINGFREQUENCY、ZBX_MAXHOUSEKEEPERDELETE
D. MySQL 侧:InnoDB buffer / redo / flush 策略(决定“写得动不动”)
Zabbix 大头是 history/trends 写入,MySQL 优化重点:
innodb_buffer_pool_size(最重要)innodb_flush_log_at_trx_commit(性能 vs 严格持久化)sync_binlog(如果开 binlog)innodb_log_file_size、max_connections、table_open_cache等
二、 生产环境的【.env】配置
适合:几百台主机、几万~十几万 items 量级(后续你看队列/忙碌度再调)

三、 docker-compose.yml【把优化项落盘 + 引用 .env】
/data/zbx7/… 落盘、网桥 zbx7-net、MySQL conf 只读挂载。
services:
# =========================
# MySQL 8.0
# =========================
mysql:
image: mysql:8.0.44
container_name: zbx7-mysql-${ZBX_INSTANCE}
hostname: zbx7-mysql-${ZBX_INSTANCE}
restart: unless-stopped
command:
- --default-authentication-plugin=mysql_native_password
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_bin
- --log-bin-trust-function-creators=1
# ---- perf tuning ----
- --innodb-buffer-pool-size=${MYSQL_INNODB_BUFFER_POOL_SIZE}
- --max-connections=${MYSQL_MAX_CONNECTIONS}
- --innodb-log-file-size=${MYSQL_INNODB_LOG_FILE_SIZE}
- --innodb-flush-log-at-trx-commit=${MYSQL_INNODB_FLUSH_LOG_AT_TRX_COMMIT}
- --sync-binlog=${MYSQL_SYNC_BINLOG}
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${ZBX_DB_NAME}
MYSQL_USER: ${ZBX_DB_USER}
MYSQL_PASSWORD: ${ZBX_DB_PASS}
TZ: ${TZ}
volumes:
- /data/zbx7/mysql/data:/var/lib/mysql
- /data/zbx7/mysql/conf:/etc/mysql/conf.d:ro
- /data/zbx7/mysql/backup:/backup
networks:
zbx7-net:
ipv4_address: ${IP_MYSQL}
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -uroot -p$${MYSQL_ROOT_PASSWORD} --silent"]
interval: 10s
timeout: 5s
retries: 30
# 按要求:不映射 13306
# =========================
# Zabbix Server
# =========================
zabbix-server:
image: zabbix/zabbix-server-mysql:7.0.22-ol
container_name: zbx7-server-${ZBX_INSTANCE}
hostname: zbx7-server-${ZBX_INSTANCE}
restart: unless-stopped
depends_on:
mysql:
condition: service_healthy
environment:
TZ: ${TZ}
DB_SERVER_HOST: mysql
DB_SERVER_PORT: 3306
MYSQL_DATABASE: ${ZBX_DB_NAME}
MYSQL_USER: ${ZBX_DB_USER}
MYSQL_PASSWORD: ${ZBX_DB_PASS}
# ---- Server tuning ----
ZBX_DEBUGLEVEL: ${ZBX_DEBUGLEVEL}
ZBX_TIMEOUT: ${ZBX_TIMEOUT}
ZBX_LOGSLOWQUERIES: ${ZBX_LOGSLOWQUERIES}
ZBX_STARTPOLLERS: ${ZBX_STARTPOLLERS}
ZBX_STARTPOLLERSUNREACHABLE: ${ZBX_STARTPOLLERSUNREACHABLE}
ZBX_STARTTRAPPERS: ${ZBX_STARTTRAPPERS}
ZBX_STARTPINGERS: ${ZBX_STARTPINGERS}
ZBX_STARTDISCOVERERS: ${ZBX_STARTDISCOVERERS}
ZBX_STARTHTTPPOLLERS: ${ZBX_STARTHTTPPOLLERS}
ZBX_STARTPREPROCESSORS: ${ZBX_STARTPREPROCESSORS}
ZBX_STARTLLDPROCESSORS: ${ZBX_STARTLLDPROCESSORS}
ZBX_STARTDBSYNCERS: ${ZBX_STARTDBSYNCERS}
ZBX_CACHESIZE: ${ZBX_CACHESIZE}
ZBX_HISTORYCACHESIZE: ${ZBX_HISTORYCACHESIZE}
ZBX_HISTORYINDEXCACHESIZE: ${ZBX_HISTORYINDEXCACHESIZE}
ZBX_TRENDCACHESIZE: ${ZBX_TRENDCACHESIZE}
ZBX_TRENDFUNCTIONCACHESIZE: ${ZBX_TRENDFUNCTIONCACHESIZE}
ZBX_VALUECACHESIZE: ${ZBX_VALUECACHESIZE}
ZBX_CACHEUPDATEFREQUENCY: ${ZBX_CACHEUPDATEFREQUENCY}
ZBX_HOUSEKEEPINGFREQUENCY: ${ZBX_HOUSEKEEPINGFREQUENCY}
ZBX_MAXHOUSEKEEPERDELETE: ${ZBX_MAXHOUSEKEEPERDELETE}
volumes:
- /data/zbx7/zabbix/alertscripts:/usr/lib/zabbix/alertscripts:ro
- /data/zbx7/zabbix/externalscripts:/usr/lib/zabbix/externalscripts:ro
- /data/zbx7/zabbix/modules:/var/lib/zabbix/modules:ro
- /data/zbx7/zabbix/snmptraps:/var/lib/zabbix/snmptraps:rw
- /data/zbx7/logs/zabbix-server:/var/log/zabbix:rw
ports:
- "${ZBX_SERVER_PORT}:10051"
networks:
zbx7-net:
ipv4_address: ${IP_SERVER}
# =========================
# Zabbix Web (Nginx)
# =========================
zabbix-web:
image: zabbix/zabbix-web-nginx-mysql:7.0.22-ol
container_name: zbx7-web-${ZBX_INSTANCE}
hostname: zbx7-web-${ZBX_INSTANCE}
privileged: true
restart: unless-stopped
depends_on:
mysql:
condition: service_healthy
zabbix-server:
condition: service_started
environment:
TZ: ${TZ}
PHP_TZ: ${PHP_TZ}
ZBX_SERVER_HOST: zabbix-server
ZBX_SERVER_NAME: ${ZBX_SERVER_NAME}
DB_SERVER_HOST: mysql
MYSQL_DATABASE: ${ZBX_DB_NAME}
MYSQL_USER: ${ZBX_DB_USER}
MYSQL_PASSWORD: ${ZBX_DB_PASS}
ZBX_WEB_ALLOW_1: ${ZBX_WEB_ALLOW_1}
ZBX_WEB_ALLOW_2: ${ZBX_WEB_ALLOW_2}
ZBX_WEB_ALLOW_3: ${ZBX_WEB_ALLOW_3}
ports:
- "${ZBX_WEB_HTTP_PORT}:8080"
# HTTPS 可选
# - "${ZBX_WEB_HTTPS_PORT}:8443"
volumes:
- ${ZBX_NGX_CONF_DIR}:/etc/nginx/conf.d:rw
- ${ZBX_TLS_CERT_DIR}:/etc/nginx/certs:rw
- ${ZBX_NGX_LOG_DIR}:/var/log/nginx:rw
networks:
zbx7-net:
ipv4_address: ${IP_WEB}
# =========================
# Zabbix Web Service(仅 amd64)
# 报表 / Dashboard 截图 / PDF
# =========================
zabbix-web-service:
image: zabbix/zabbix-web-service:7.0.22-ol
container_name: zbx7-web-service-${ZBX_INSTANCE}
hostname: zbx7-web-service-${ZBX_INSTANCE}
restart: unless-stopped
environment:
ZBX_ALLOWEDIP: 0.0.0.0/0
TZ: ${TZ}
volumes:
- /data/zbx7/logs/web-service:/var/log/zabbix:rw
networks:
- zbx7-net
# 内部端口 10053,不需要对外暴露
# =========================
# Zabbix Java Gateway
# =========================
zabbix-java-gateway:
image: zabbix/zabbix-java-gateway:7.0.22-ol
container_name: zbx7-web-gw-${ZBX_INSTANCE}
hostname: zbx7-web-gw-${ZBX_INSTANCE}
restart: unless-stopped
environment:
TZ: ${TZ}
networks:
zbx7-net:
ipv4_address: ${IP_JAVA_GW}
# =========================
# Zabbix Agent2
# =========================
zabbix-agent2:
image: zabbix/zabbix-agent2:7.0.22-ol
container_name: zbx7-agent2-${ZBX_INSTANCE}
hostname: zbx7-agent2-${ZBX_INSTANCE}
restart: unless-stopped
environment:
ZBX_SERVER_HOST: zabbix-server
ZBX_HOSTNAME: ${AGENT_HOSTNAME}
TZ: ${TZ}
networks:
zbx7-net:
ipv4_address: ${IP_AGENT2}
# =========================
# Grafana
# =========================
grafana:
image: grafana/grafana:12.3.1
container_name: zbk7-grafana-${ZBX_INSTANCE}
hostname: zbk7-grafana-${ZBX_INSTANCE}
restart: unless-stopped
environment:
TZ: ${TZ}
GF_SECURITY_ADMIN_USER: ${GRAFANA_ADMIN_USER}
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD}
# 可选:允许匿名访问(不建议生产开启)
# GF_AUTH_ANONYMOUS_ENABLED: "true"
ports:
- "${GRAFANA_PORT}:3000"
volumes:
- /data/zbx7/grafana/data:/var/lib/grafana:rw
- /data/zbx7/logs/grafana:/var/log/grafana:rw
# 可选:自动导入数据源/仪表盘(你后面要再加)
- /data/zbx7/grafana/provisioning:/etc/grafana/provisioning:ro
networks:
zbx7-net:
ipv4_address: ${IP_GRAFANA}
networks:
zbx7-net:
name: zbx7-net
driver: bridge
ipam:
config:
- subnet: ${ZBX_NET_SUBNET}
gateway: ${ZBX_NET_GW}


四、 你上线后怎么判断“这些值该不该继续加/减”
建议在 Zabbix 里给 server 本机套用模板(Zabbix server 自监控),盯三类指标:
Queue(采集队列)是否堆积
各类进程 busy%(poller/preprocessor/dbsyncer 等是否长期高于 70%)
缓存命中/使用率(cache 是否经常满)
对应策略很直接:
poller busy 高 + queue 堆积 → 加
ZBX_STARTPOLLERSpreprocessing busy 高 → 加
ZBX_STARTPREPROCESSORSdbsyncer busy 高 / DB 写入慢 → 加
ZBX_STARTDBSYNCERS或先优化 MySQLcache 满/抖 → 增大
ZBX_*CACHESIZE
(7天 history 场景最常见的“下一步优化”)
你如果发现 queue 不堆、busy% 很低:可以继续把
StartPollers/Preprocessors小幅下调,减少上下文切换。如果发现 dbsyncer busy 高:优先看磁盘写延迟、MySQL redo/flush;7天一般不需要上分区。
如果你把 items 的类型占比(agent passive/active、SNMP、HTTP、trap)告诉我,我还能把 poller/http poller/trapper/preprocessor 的比例配得更“贴脸”。
(30天 history = 尽快做 MySQL 分区)
如果你坚持 30 天 history,最稳的长期解法是对 history/trends 表做分区,让“删除过期数据”变成 DROP PARTITION,从 “删百万行” 变成 “删一个分区”,DB 压力会小很多。Zabbix 官方博客也专门给了 MySQL 8 的分区方案思路。
你可以先按方案A跑起来,然后在业务低谷窗口做分区迁移(通常要短暂停写或做切换)。
https://blog.zabbix.com/partitioning-a-zabbix-mysql-database-with-perl-or-stored-procedures/13531/

你上线后,用这 3 个指标判断“还要不要再调”
housekeeper busy(如果长期高,说明 delete 压力太大 → 要么再降
MaxHousekeeperDelete,要么上分区)dbsyncer busy / history write(高则 DB 写入顶住了)
queue(如果队列有堆积,再加 poller/预处理)