# ROMAN 定制中心 — 使用与部署说明 > 适用版本:Zabbix **7.4.x**(已在 7.4.16 / MySQL 8.0.43 验证)。 > 一个自包含、多语言的 Zabbix 前端模块(custom module / plugin)。加载后会在 > **Administration → ROMAN 定制中心** 增加一个定制页面,分 **告警 / 优化 / 日常维护 / L2 拓扑** 四个标签页。 --- ## 1. 它能做什么(一句话版) | 标签页 | 关键能力 | |---|---| | **告警 Alert** | 企业微信群机器人 key 设置与测试;5 套告警策略预设(**先预览 → 再应用**);手动勾选会通知的严重度;一键刷新(写入模板触发器 / 触发器原型 / 已发现触发器,全部节点生效)。 | | **优化 Optimization** | 服务端调优参数生成(只生成 `.env`/compose 片段与重建命令,**不落地**,运维自行重建);真实华为模板 →「导入」→「切换」迁移设备;Geomap 单点标记。 | | **日常维护 Maintenance** | **按类别批量改告警等级**;**按单个触发器精确调整**:勾选开关告警 + 行尾下拉改严重度;**保存后页面自动刷新**。 | | **L2 拓扑 Topology** | 一张只读全局物理拓扑;STP/MAC 协议关系、7 天快照历史、单面板时间选择器;PNG 导出、终端端口矩阵、告警/离线/延迟/速率着色。 | 所有改动都走 **Zabbix 官方 API / 受控 SQL** 写进数据库,所以**换机器、重建容器、升级镜像,配置都在**——只要「加载插件」即可复用。 --- ## 2. 部署 ### 2.1 全新 Zabbix(推荐,一条命令就有插件) 仓库自带的 `docker-compose.yaml` 已经把「插件随仓库走 + 自动启用」做好: ```bash git clone <本仓库地址> zabbix-deploy cd zabbix-deploy # (可选)已有环境的模块目录在别处时,用环境变量覆盖,默认是仓库同级的 ./web-modules # export WEB_MODULES_DIR=/opt/zabbix/zabbix-server/web-modules docker compose up -d ``` 启动后: - 文件层面:`./web-modules/WecomCenter` 被挂到容器 `/usr/share/zabbix/modules/WecomCenter`。 - 数据层面:一次性服务 **`wecom-module-init`** 会等 MySQL 和 Zabbix 的 `module` 表就绪后,把 `wecom_center` 登记为 **已启用(status=1)**,并创建 L2 两张表。脚本是**幂等**的:已存在就不动,重复 `up` 也安全;不会因首次建库时序而失败。 > 也就是说:**全新环境 `up -d` 完,什么都不用点,插件已经在了。** ### 2.2 已有 Zabbix(手动装) 1. 确认 web 容器挂载了持久化的 modules 目录(否则重建容器文件会丢): ```yaml zabbix-web-nginx-mysql: volumes: - /opt/zabbix/zabbix-server/web-modules:/usr/share/zabbix/modules ``` 2. 把 `web-modules/WecomCenter` 整个目录拷到宿主那台目录下(即 `.../web-modules/WecomCenter/`)。 - 也可用自带脚本:`cd web-modules && ./install.sh`(自动探测运行中的 `zabbix-*` web 容器并复制进去;或 `./install.sh /usr/share/zabbix/modules`)。脚本会顺带建 L2 表,并在 `module` 表已就绪时**自动登记/启用** `wecom_center`;复制前还会扫描 PHP/JS 源文件,发现 UTF-8 双重编码乱码会直接报错退出。 3. `docker compose up -d` 重建 web 容器使挂载生效(只重启 web,数据不动)。 4. 若脚本提示 `module` 表尚未就绪,等 Zabbix 首次启动完成后,进 **Administration → General → Modules → Scan directory → 启用 `WecomCenter`**;也可以手工执行: ```sql SET @nid := (SELECT COALESCE(MAX(moduleid),0)+1 FROM module); INSERT INTO module(moduleid,id,relative_path,status,config) SELECT @nid,'wecom_center','modules/WecomCenter',1,'[]' WHERE NOT EXISTS (SELECT 1 FROM module WHERE id='wecom_center'); ``` ### 2.3 换环境 / 升级镜像 - 换机器:把仓库(含 `web-modules/`)拉过去,按 2.1 或 2.2 重来即可;数据库卷保留则配置不丢。 - 升级镜像:镜像锁定精确版本(`ubuntu-7.4.16`),`up -d` 重建后插件仍在(文件在挂载目录、启用记录在 DB)。 ### 2.4 部署验证 1. 左侧菜单出现 **Administration → ROMAN 定制中心**,点开能看到四个标签页(告警 / 优化 / 日常维护 / L2 拓扑)即成功。 2. 打开 **日常维护** 页能搜到触发器、每行右侧有严重度下拉,说明读写链路正常。 3. 看 `/opt/zabbix/zabbix-server/web-modules/WecomCenter/manifest.json` 与 DB 的 `module` 行(`id=wecom_center,status=1`)。 --- ## 3. 首次初始化(告警链路一键补全) 安装后第一次打开 **ROMAN 定制中心 → 告警** 页,会显示 **First-time setup / 首次配置**: 1. 粘贴企业微信群机器人 webhook 的 **Key**(就是 `https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=...` 里 `key=` 后面那串)。 2. 点 **初始化环境 / Initialise(自检)**。它会自动补齐整条告警链路,**缺啥建啥、已存在则复用**,可反复点当作自检: | 对象 | 作用 | |---|---| | 全局宏 `{$WECOM_KEY}` | 存放机器人 key(换机器人只改这一格) | | 媒体类型 `WeCom Group Robot` | type=4 webhook,内置发送脚本(markdown,失败回退 text) | | 机器人用户 `wecomrobot` | 挂上面这个媒体类型,severity = High + Disaster | | 触发器动作 `Send alarm by Wecom Robot` | 告警发红字、恢复发绿字,均带 `{$ZBX_URL}` 直达详情链接 | > 群机器人就是「往群里发一条消息」,**没有收件人账号/接收目标**的概念,所以这里不设真人接收者,只维护一个机器人账号承载媒介。 **拓扑初始化**:同一次「初始化 / 自检」也会幂等创建 L2 拓扑的 `l2_topology_history` / `l2_topology_config`,并在配置行缺失时写入默认配置(已有配置绝不覆盖)。如果只想初始化拓扑、不碰告警链路,到 **ROMAN 定制中心 → L2 拓扑** 顶部点 **「初始化 / 自检 L2 存储」** 即可。采集器 cron 仍需按 10.4 在宿主机安装,容器不会替你做 SNMP 采集。 --- ## 4. 页面使用详解 ### 4.1 告警 Alert - **机器人 key**:单字段读写全局宏 `{$WECOM_KEY}`;点 **发送测试** 会直接打企微接口,返回 `errcode:0` 即通。 - **告警策略预设**:内置 5 套(稳健运维 / 只保命 / 全量观察 / 夜间降噪 / 核心从严)。 - **先「预览」(dry-run,不写库)**:按类别列出将改动多少触发器。 - **再「应用」**:①设媒介严重度阈值;②把「模板触发器、触发器原型、已发现(LLD)触发器」按类别批量改严重度。**必告警类别一律钉到灾难 Disaster(5)**,所以阈值再高也必然发出。可重复执行、可回滚。 - **手动阈值**:勾选「会通知」的严重度 + 总开关(写媒介 `severity` 位掩码 / `active`)。 - **一键刷新**:应用/保存后,改动通过 API 立即下发模板、通过受控 SQL 写已发现触发器;**所有探测节点(模板 → 主机)都会同步**。前端读库即时可见,Zabbix server 配置缓存约 **60 秒**内自动同步到告警判定。 ### 4.2 优化 Optimization - **服务端调优生成器**:选 小/中/大 规模,生成 `StartSNMPPollers` 等 `.env`/compose 参数与重建命令。**只生成、不落地**,由运维复制到主机自行 `docker compose up -d` 重建 server(零风险、零特权)。 - **模板导入**:内置的是**真实的华为模板** `Huawei VRP by SNMP walk`(导出文件在 `templates/`),点「导入」即导入 Zabbix(已存在则就地更新,新模板则新建)。 - **模板切换(迁移设备)**:选「旧模板 → 新模板」→ **预览**列出受影响设备 → **确认切换**,把每台设备的模板链接替换为新模板(保留其它链接、去重)。 - **地图标记**:以 **单点(Zabbix server 主机)** 作代表点设置经纬度。 > Geomap 底图需**浏览器能访问外网**加载 OSM 瓦片;纯内网底图会空白,但标记点逻辑正确。 ### 4.3 日常维护 Maintenance(本次重点) **A. 按类别批量改告警等级** 1. 「Trigger class」选一个类别(设备离线 / 硬件故障 / 重启 / 核心链路 / 接口 down / 性能 …;`other` 不参与)。 2. 「Set severity to」选目标严重度(Not classified … Disaster)。 3. 点 **Apply**。会把该类别下的**模板触发器、触发器原型、已发现(LLD)触发器**一次性改到该等级,并自动刷新列表。 - 与「策略引擎」同一套写入逻辑,**完全可逆**;适合「把某一类警报统一拉高/压低」。 **B. 按单个触发器精确调整** 1. 顶部搜索框输入关键字(如 `Temperature`)→ 点 **Search**(最多显示 200 条;全库可能有数万个触发器)。 2. 每一行: - 左侧 **勾选框**:勾选 = 启用告警,取消 = 停用该触发器(写 `trigger.status`,0 启用 / 1 停用); - 右侧 **下拉框**:直接选该触发器的严重度(0–5)。 3. 改完点 **Save**,**页面自动刷新**,结果立即列出;server 配置缓存约 60 秒内同步到告警判定。 > 所有调整只改 `triggers.priority` / `triggers.status`,**不删除任何对象**。对「已发现(LLD)触发器」因 Zabbix API 不允许改其 priority,改用**受控 SQL** 精确更新,可逆。 --- ## 5. 严重度对照 | 等级 | priority | 媒介位掩码 | |---|---|---| | 未分类 Not classified | 0 | 1 | | 信息 Information | 1 | 2 | | 警告 Warning | 2 | 4 | | 一般严重 Average | 3 | 8 | | 严重 High | 4 | 16 | | 灾难 Disaster | 5 | 32 | - 触发器「是否告警」= `trigger.status`(**0 启用 / 1 停用**)。 - 媒介「是否生效」= `media.active`(**0 启用 / 1 停用**),严重度用位掩码。 --- ## 6. 多语言 - 共 **35 个语言文件**,覆盖 Zabbix 全部 locale(`en_GB`/`en_US` 共用英文),与 Zabbix 语言数量一致。 - 已人工翻译:`zh_CN`、`zh_TW`、`ja_JP`、`ko_KR`、`ru_RU`、`de_DE`、`fr_FR`、`es_ES`、`pt_BR`、`it_IT`、`pl_PL`、`tr_TR`。 - 其余语言文件存在,运行时**自动回退英文**(页面照常工作,不报错)。 - 模块按**当前用户界面语言**自动切换。新增/完善某语言:复制 `locale/en.php` 为 `locale/.php`,只改 value、键名不变即可。 --- ## 7. 常见问题(FAQ) **Q:改完严重度,为什么告警没立刻变?** A:页面(读数据库)会**立刻**显示新值;Zabbix server 的「配置缓存」约 **60 秒**(`CacheUpdateFrequency`)刷新后才作用于告警判定。这是 Zabbix 机制,不是插件问题。 **Q:地图是空白的?** A:Geomap 底图依赖浏览器访问外网 OSM 瓦片;纯内网会空白,但标记点逻辑正确。 **Q:会不会误伤生产触发器?** A:不会。所有操作都要**你主动点 Apply / Save** 才写库;「预览」不写库;改动仅限 `priority` / `status`,不删对象,且可用备份回滚。 **Q:换机器人 key 要改哪里?** A:只改页面「机器人 key」一处(即全局宏 `{$WECOM_KEY}`),或 Administration → Macros。 **Q:能在非 docker 的 Zabbix 上用吗?** A:可以。把 `WecomCenter/` 放到 `modules` 目录、启用模块即可(见 2.2)。 **Q:升级 Zabbix 会丢插件吗?** A:不会。插件文件在宿主持久化目录、启用记录在数据库;只要目录与数据库卷保留,升级镜像后仍在。 --- ## 8. 目录结构 ``` zabbix-deploy/ ├── docker-compose.yaml # 带插件:挂载 ./web-modules + wecom-module-init 自动启用 ├── web-modules/ │ ├── install.sh # 一步搬运脚本(docker 自动探测 / 指定目录) │ ├── README.md # 开发者向说明 │ └── WecomCenter/ # 插件本体 │ ├── manifest.json # v2.0.1(manifest_version 2.0),注册 2 个 action │ ├── Module.php # 入口:注册视图、i18n、注入左侧菜单 │ ├── actions/ # View(GET) / Save(POST) 控制器 │ ├── views/ # 页面模板 │ ├── lib/ # I18n.php / Helper.php(业务逻辑) │ ├── locale/ # 35 个语言文件 │ ├── templates/ # 内置真实华为模板 │ └── assets/ # wecom.center.css └── docs/使用说明.md # 本文档 ``` --- ## 9. 回滚建议 动手批量改前,建议先导出相关对象做备份(媒介类型、动作、全局宏、触发器 priority 快照)。示例(API 导出): ```bash # 用 API token 导出媒介/动作/宏,保存为 JSON,需要时用对应 API 还原 ``` 页面「预览」永远是 dry-run,先看影响面再应用,是最稳的做法。 --- ## 10. L2 物理拓扑(ROMAN 定制中心模块内置) ### 10.1 访问入口 - 展示页:**Monitoring → L2 Topology**,或直接 `http://192.168.87.20:8080/zabbix.php?action=l2.topology.view` - 配置页:**Administration → ROMAN 定制中心 → 「L2 拓扑」标签**(模块改名为“ROMAN 定制中心”, 配置项全部集中在配置页,展示页只读)。物理网络在「物理网络定义」中按每行 `KEY | 显示名称 | 名称/IP关键字 | #RRGGBB` 配置,例如 `SURVE | SURVE 监控网 | SURVE,10.169. | #2E75B6`;新增/减少网络只改这里。 - 「核心交换机」与分组规则一样可逐行添加:每行选择网络(或全部网络)、匹配方式(contains/regex)、 名称/IP 规则。命中的交换机全部画在最左侧核心列;同一网络可定义多个核心,顺序不限。 ### 10.2 展示页功能 - **链路速率配色**(可在配置页改): - 100M = 橙色 `#F39C12`,1G = 绿色 `#2ECC71`,10G = 蓝色 `#3498DB`, 20G+ = 紫色 `#9B59B6`,未知 = 红色 `#E74C3C`,中断 = 红色虚线 `#C0392B`。 - **延迟着色**:默认 ping 交换机管理 IP(Zabbix 主机 → 交换机), >3ms 橙色、>5ms 红色(阈值可配)。注:本网实测 0.8ms 左右,绝大多数为正常(无色)。 - **一张全局大拓扑图**(不再有卡片全景/车间详情两级): - 从左到右固定为 **核心(可多个)→ 各网络主交换 → 各车间汇聚/分布 → 接入**,一级交换机一列;列只按层级区分, 不按车间拆成多列。 - 每个车间一个框(包住该车间的汇聚+接入),框内按 **GRD → 1F → 3F → 4F → 7F** 从下到上画楼层小框, 每层接入交换机在该楼层框内排列;接入下还有接入时按层级向右加一列(不改协议连接关系)。同一车间跨网络时拆成两个独立框,只连接各自网络的上游。 - 所有链路均为单段直线,从**上级标签左缘中点**画到**下级标签左缘中点**;上级标签可以遮住线路出口, 但任何目标标签和其他线路不被遮挡;同一车间内部线路互不交叉,跨区直连核心的链路除外。点任意交换机高亮完整上联链路,点空白恢复。 - **数据流动效果**:正常在线链路叠加从核心向下游流动的细虚线(下行/离线链路不流动), 100M/1G/10G/20G+ 的流动速度依次加快,仅作视觉提示,不改变任何连接关系。 - **PoE 交换机**:采集器优先通过 RFC3621 `pethPsePortAdminEnable` 和华为 `hwPoePortJudgeIsSupport` 判断;部分华为固件不开放 HUAWEI-POE-MIB 时,再用 ENTITY-MIB `entPhysicalDescr` 的型号描述(如 `S5735-L24P4XE-A-V2 ... PoE+`)兜底。支持 PoE 的交换机名称最前面显示 `⚡️`;当前离线或 SNMP 无响应的设备不显示。 - **节点标签**:`车间 · 楼层机柜U · 角色 · IP`;双击节点跳转该主机的问题页。 - **告警/离线/延迟着色**:告警交换机整个节点填充红色,离线交换机同样整节点红色;延迟 **3–5ms 为橙色边框**,**大于 5ms 才为红色边框**。告警不会再只画一个红框。告警面板只显示拓扑内交换机,不混入服务器/测试机等“拓扑外”主机。 - **显示终端(端口矩阵)**:勾选「显示终端」后,接入/汇聚交换机下方按实际端口清单绘制圆点;外圈颜色表示该端口**支持的最大速率**(100M 橙、1G 绿、2.5G 青、10G 紫、20G+ 深紫、未知灰),圆心实心颜色表示该端口**当前实际链路速率**。例如:10G 口插 1G 线 = 紫色外圈 + 绿色实心;10G 口未插线 = 空心紫色圈;2.5G 口 = 青色圈。端口较多时按实际面板自动分两行/多行,上联端口单独成行;历史快照没有端口清单时退回通用 24 口两行矩阵(12+12),不丢已有终端位置。端口颜色与上方链路速率颜色是两套语义,不要混用。 - 右侧「离线交换机」面板可查看离线交换机并点击定位;终端面板点击任意终端可定位到其接入交换机及具体端口。 - **时间轴**:右上「快照时间」是一个下拉面板(不是两个并排选择框):左侧只列实际保存过快照的日期(含「实时(最新)」),点日期后右侧只列该日期实际保存过的时间点,点时间即切换;默认 5 分钟一个点,保存 7 天;`采集/快照间隔`和`历史保留天数`都在配置页可调;采集成功即保存,不再单独设置快照间隔。 - **明暗主题**:自动跟随 Zabbix 当前主题(Zabbix 深色即深色、亮色即亮色),无手动开关。 - **搜索**:输入 IP / MAC / 名称,下拉结果点击即居中定位。 - **导出图片**:右上角「导出图片」把当前完整拓扑导出为 PNG;无论当前 Zabbix 是明色还是深色,导出图固定使用日间模式(白底), 且导出时隐藏流动虚线,保证静态图上的实线/红虚线含义清晰。 - 实时模式按配置的刷新秒数自动刷新,可暂停;支持缩放/适应窗口。 ### 10.3 数据与存储 - 采集结果 → `assets/l2topology/snapshot.json`(展示页实时读取)。 - 每次全量采集成功后,按配置的 `full_interval_min`(默认 5 分钟)把快照 gzip 后写入 MySQL 表 `l2_topology_history` (字段 ts、captured_at、stats、snapshot),并自动清理超过 `history_days`(默认 7 天)的旧数据; 每分钟告警刷新只更新实时 JSON,不重复写历史。 按当前约 822 KB 原始 JSON / 约 33 KB gzip 压缩后估算:5 分钟 × 7 天 = **2,016 条**,约 **65–75 MB**; 10 分钟约 33 MB,1 分钟约 330 MB。默认 5 分钟/7 天不夸张。 - 配置存 `l2_topology_config`(单行 id=1),并镜像到 `assets/l2topology/config.json` 供采集脚本读取。 - 两张表由 `L2Store::ensureSchema()` 在页面加载时自动 `CREATE TABLE IF NOT EXISTS`; `docker-compose.yaml` 的 `wecom-module-init` 一次性容器也会在 `up` 时建表,全新环境零手工。 - 手动安装/升级后可在 **L2 拓扑配置页顶部**点 **「初始化 / 自检 L2 存储」**:幂等建表、配置行缺失时写默认配置,不覆盖已有配置。它与告警「初始化 / 自检」是同一套幂等逻辑,但不会创建/修改任何 Zabbix 用户或告警对象。 ### 10.4 采集器(宿主机运行) 采集器代码位于仓库 `collector/`,安装到 `/opt/zabbix/l2collector/`: ``` stp_collect.py # STP 指定桥 + MAC 学习 -> 交换机级联关系 fdb_collect.py # ARP + BRIDGE-MIB FDB + ifName -> 终端/链路 fdb_analyze3.py # 归并出链路与终端清单 port_status.py # IF-MIB 端口 up/down/速率/每口 MAC 数 latency_collect.py # 并发 ping 交换机管理 IP -> /tmp/latency.tsv l2_snapshot.py # 合成 snapshot.json + 按配置间隔写历史库 l2cfg.py # 读取 config.json,按模板过滤要采集的主机 run_full.sh # 全量:stp->fdb->analyze->port->latency->snapshot(写历史) refresh_alarms.sh # 仅刷新实时告警 JSON(每分钟;不写历史) ``` - **只采集配置页所选模板**(默认 `Huawei VRP by SNMP (walk)`,id 10962)的主机,避免误采其它设备。 - 安装(一次性,幂等): ```bash cd /opt/zabbix/l2collector && chmod +x run_full.sh refresh_alarms.sh { crontab -l 2>/dev/null | grep -v l2collector || true echo '*/5 * * * * /bin/bash /opt/zabbix/l2collector/run_full.sh >/dev/null 2>&1' echo '* * * * * /bin/bash /opt/zabbix/l2collector/refresh_alarms.sh >/dev/null 2>&1' } | crontab - ``` - 手动跑一次全量:`bash /opt/zabbix/l2collector/run_full.sh`,日志 `/var/log/l2collector.log`。 ### 10.5 docker-compose 一键启用 - `docker-compose.yaml` 已把 `web-modules/` 挂进 `zabbix-web` 容器, 并由 `wecom-module-init` 一次性容器等待 Zabbix 的 `module` 表就绪后自动登记(启用)模块、创建 L2 两张表。 全新机器 `docker compose up -d` 后插件即已启用,无需手工去「Administration → Modules」点启用。 全新库首次创建 `module` 表需要一点时间,侧车最多等 300 秒,避免首次 `up` 时序失败。 - 若 `web-modules` 目录不在 compose 同级,用 `.env` 的 `WEB_MODULES_DIR` 指向绝对路径。 - 采集器为宿主机进程(需 SNMP 工具、且要读交换机网络),不在容器内运行,按 10.4 安装。 ### 10.6 故障排查 - 按钮出现 `鈼?`、`鉂氣潥`、`锛?` 等乱码:不是浏览器字体问题,而是 `views/topology.view.php` 被按 GBK/ANSI 重新编码。2.0.1 起已全部改为 HTML 数字实体;请重跑 `install.sh` 覆盖旧文件,安装脚本会检测并拒绝带 mojibake 的包。 - 展示页空白:确认 `assets/l2topology/snapshot.json` 存在(跑一次 `run_full.sh`)。 - 时间轴没有历史:确认 cron 在跑、`l2_topology_history` 行数在增长;历史写入间隔最少 5 分钟,改配置页后需等下一个周期。 - 交换机没被采集:检查配置页模板是否勾选正确、该主机是否挂了该模板、SNMP 可达。 - 颜色/阈值不生效:改完配置页保存后,`config.json` 会同步;采集侧下个周期生效。