1. 园区巡检告警闭环,为什么“发出去”不等于“处理完”
做园区 AI 巡检系统的团队,十有八九会把注意力压在算法侧:摄像头选型、模型精度、误报率、边缘盒子算力。这些当然重要,但真正让一线运维骂娘的,往往不是“没检测到”,而是“检测到了,然后呢”。告警弹出来了,工单建了,IM 群里也 @ 了人,结果三天后同一台设备还在报同样的故障——这就是典型的告警闭环断裂。
我参与过两个园区的 AI 巡检项目,一个偏工业场景(PLC、传感器、数控机床状态采集),一个偏楼宇场景(环境传感器、光电传感器、人员靠近检测)。两个项目在告警闭环上都栽过跟头,而且坑的形态高度相似。这篇就把这 5 个坑摊开讲,包括每个坑的根因、排查链路、修复方案,以及我后来总结出的“闭环设计检查清单”。如果你正在做 AI 巡检、工单系统、IM 告警推送,或者负责园区设备运维数字化,这篇应该能帮你省掉至少两轮返工。
先说清楚“告警闭环”在我这里的定义:从传感器/算法产生告警,到工单派发、处理、验收、归档,并且状态可追溯、可统计、可复盘。注意最后三个词——可追溯、可统计、可复盘。很多系统只做到了“告警能发出去”,离闭环还差得远。下面 5 个坑,基本都踩在这三个词上。
2. 坑一:告警风暴把 IM 群冲垮,根因不在推送频率
2.1 现象:一个 Modbus 点位抖动,群里刷了 200 条消息
项目上线第二周,运维群里突然炸了。某台数控机床的振动传感器通过 Modbus 协议上报的数据出现高频抖动,AI 巡检规则判定为“设备异常振动”,于是每 10 秒触发一次告警。IM 机器人老老实实每条都推,半小时刷了 200 多条。运维主管直接在群里说:“把这机器人关了。”
表面看是推送频率问题,实际上根因有三层:
- 数据层:Modbus 读取的是原始寄存器值,没有做滑动窗口平滑,传感器本身的噪声被当成真实异常。
- 规则层:告警规则没有设置“持续时长”条件,瞬时越限就触发。
- 推送层:IM 推送没有做聚合和去重,每条告警独立发送。
2.2 修复:三层各自加一道闸
数据层我加了一个 5 点滑动平均,针对振动、温度这类连续量,先平滑再进规则引擎。代码不复杂,但效果立竿见影:
# 滑动窗口平滑,窗口大小5 from collections import deque class MovingAverage: def __init__(self, size=5): self.window = deque(maxlen=size) def update(self, value): self.window.append(value) return sum(self.window) / len(self.window)规则层加了“持续时长”和“冷却时间”两个参数。持续时长指越限必须连续保持 N 秒才触发;冷却时间指同一告警触发后,M 分钟内不再重复触发。这两个参数我一般建议:持续时长 30 到 60 秒,冷却时间 5 到 15 分钟,具体看设备类型。
推送层做了聚合:同一设备、同一告警类型在 5 分钟窗口内合并为一条消息,消息里带“已触发 N 次”的计数。IM 消息格式也改了,从纯文本改成结构化卡片,包含设备编号、告警等级、首次触发时间、最近触发时间、处理入口链接。
提示:聚合窗口不要设太长。我试过 30 分钟聚合,结果运维说“告警来得太慢,设备都停了才收到”。5 到 10 分钟是比较舒服的区间。
2.3 一个容易被忽略的细节:告警等级要能“升级”
聚合之后有个新问题:如果一条告警被聚合了 10 次还没人处理,它应该升级。我的做法是设阈值——同一告警聚合计数超过 5 次,自动从“一般”升级为“严重”,并改变 IM 消息的颜色和 @ 对象。这个逻辑后来救过一次场:某配电房温度传感器持续越限,前 5 次聚合在一般等级,第 6 次升级后 @ 了值班主管,才发现是空调故障导致室温飙升。
3. 坑二:工单建了但没人接,派工逻辑比你想的复杂
3.1 “自动派工”为什么派不动
告警闭环的核心载体是工单。我最初的设计很朴素:告警触发后自动创建工单,按设备所属区域分配给对应运维人员。上线后发现大量工单卡在“待接单”状态,平均接单时长超过 4 小时。
排查下来,问题出在派工逻辑太“静态”:
- 区域负责人是写死的,但实际排班是轮班制,写死的人可能当天休息。
- 没有考虑人员当前工单负载,忙的人越派越多,闲的人没单。
- 工单优先级没有和告警等级挂钩,所有工单长得一样。
3.2 我后来用的派工策略
改版后的派工逻辑分四步:
- 确定候选池:根据设备位置和故障类型,筛选具备对应技能标签的在班人员。
- 负载排序:按当前未完成工单数升序排列,负载相同则按最近接单时间排序。
- 优先级映射:告警等级“严重”映射为工单优先级 P0,“一般”映射为 P2,P0 工单跳过负载排序直接派给技能匹配度最高的人。
- 超时兜底:工单创建后 15 分钟无人接单,自动升级到上级主管,并再次推送 IM。
这里有个经验:技能标签体系不要一开始就设计得太细。我见过有团队把技能标签做到 50 多个,结果派工匹配率极低。园区场景下,10 到 15 个标签足够覆盖,比如“电气”“暖通”“安防”“网络”“传感器”“PLC”这些。
3.3 工单状态机必须和告警状态联动
这是我在第二个项目才想明白的事。工单和告警是两张表,但状态必须联动:
| 告警状态 | 工单状态 | 联动动作 |
|---|---|---|
| 新建 | 待派发 | 触发派工逻辑 |
| 已派发 | 待接单 | 推送 IM 通知 |
| 处理中 | 处理中 | 暂停告警重复推送 |
| 已恢复 | 待验收 | 通知验收人 |
| 已关闭 | 已归档 | 记录闭环时长 |
如果告警恢复了但工单还在“处理中”,系统应该自动把工单转为“待验收”,而不是等人手动改。我踩过的坑就是:设备自己恢复了,工单还挂着,运维白跑一趟。
4. 坑三:传感器数据“看起来正常”,但闭环判断错了
4.1 环境传感器不是正态分布,别用均值做基线
这个坑比较隐蔽。楼宇场景里我用了大量环境传感器(温湿度、光照、CO2),最初做异常判断用的是“均值 ± 3 倍标准差”。结果发现误报率极高,尤其是光照传感器,早晚变化剧烈,天天报异常。
后来查资料才意识到:很多环境传感器数据不是正态分布。光照、CO2 这类数据受作息、天气影响,分布是偏态的,甚至双峰的。用正态分布假设去做基线,本身就是错的。
我的修正方案是改用分时段基线:把一天切成 24 个小时段,每个时段单独统计历史数据的 P10 和 P90 分位数,超出分位数范围才告警。这个方法对偏态分布更鲁棒,误报率降了大概 70%。
4.2 光电传感器和霍尔传感器的“状态型”数据怎么处理
园区里还有一类传感器是状态型的,比如对射式光电传感器(检测门是否被遮挡)、霍尔传感器(检测电机转速或位置)。这类数据不是连续量,而是开关量或脉冲量。
状态型数据的闭环判断逻辑完全不同:
- 开关量:关注“状态持续时间”。比如门被遮挡超过 5 分钟,才判定为异常,而不是一遮挡就报。
- 脉冲量:关注“频率突变”。比如霍尔传感器测转速,转速从 1500 骤降到 0,这是异常;但正常启停也会到 0,所以要结合设备运行状态判断。
我当时的错误是把状态型数据也塞进了连续量的规则引擎,导致大量误报。后来在数据接入层就做了分类,连续量走平滑+分位数,状态量走持续时间+状态机。
4.3 加速度陀螺仪传感器的数据要“看趋势”而不是“看瞬时值”
有个场景是检测人员靠近或静止(距离 0.1 到 1 米),用的是加速度陀螺仪传感器。这类传感器的原始数据噪声很大,瞬时值几乎没有意义。我的做法是计算短时能量和方差,用 1 秒窗口的方差来判断“是否有活动”,而不是看单点加速度值。
这个思路后来也用在设备振动监测上:不只看振动幅值,还看振动频率的变化趋势。趋势突变往往比幅值越限更早预示故障。
5. 坑四:IM 推送和工单系统“两张皮”,状态对不上
5.1 消息里的“处理”按钮点了没反应
这是最尴尬的坑。IM 告警消息里放了一个“立即处理”按钮,点进去应该跳转到工单详情页并自动接单。结果上线后发现,按钮点了要么没反应,要么跳转后工单状态没变。
根因是 IM 机器人和工单系统之间没有做状态同步。IM 侧只负责推送,工单侧只负责存储,两边靠一个中间表同步,但中间表有延迟,而且失败没有重试。
5.2 我的修复方案:以工单系统为唯一状态源
改版后的架构原则是:工单系统是唯一状态源,IM 只是展示和操作入口。具体做法:
- IM 消息里的所有操作按钮,点击后调用工单系统的 API,由工单系统更新状态。
- IM 消息的展示状态通过定时拉取工单状态来刷新,而不是自己维护一份。
- 如果 IM 操作失败,要有明确的错误提示,并引导用户到工单系统操作。
这里有个技术细节:IM 消息的“更新”能力因平台而异。有些 IM 支持更新已发送消息的内容(比如卡片消息),有些不支持。如果不支持,我的做法是发送一条新消息说明状态变更,而不是让旧消息一直显示错误状态。
5.3 高并发 IM 场景下的消息顺序问题
园区规模大了之后,IM 推送量会上去。我遇到过消息乱序的问题:先发的“告警恢复”消息后到,后发的“告警触发”消息先到,运维看得一头雾水。
解决方案是给每条消息带一个单调递增的序列号,IM 侧收到后按序列号排序展示。如果 IM 平台不支持排序,就在消息内容里带上时间戳和序列号,让用户能自己判断。
注意:不要依赖 IM 平台的消息时间戳做排序,那个时间戳是服务端接收时间,不保证和发送顺序一致。
6. 坑五:闭环数据没有沉淀,复盘时“查无此单”
6.1 告警关了,但数据没留
项目跑了一个月,领导问:“这个月哪类告警最多?平均闭环时长多少?哪些设备反复出问题?”我打开数据库一看,告警记录有,工单记录有,但两者之间的关联字段是空的。也就是说,我知道有 500 条告警,也知道有 300 个工单,但不知道哪条告警对应哪个工单。
这是典型的“重流程、轻数据”问题。闭环不只是把流程走完,还要把数据留下来。
6.2 我后来补的闭环数据模型
补的数据模型核心是三张表加一个宽表:
- 告警表:告警 ID、设备 ID、告警类型、等级、触发时间、恢复时间、状态。
- 工单表:工单 ID、告警 ID(外键)、处理人、创建时间、接单时间、完成时间、验收时间、状态。
- 处理记录表:记录 ID、工单 ID、操作人、操作类型、操作时间、备注。
- 闭环宽表:按天聚合,包含告警数、工单数、平均接单时长、平均处理时长、平均闭环时长、重复告警设备数。
宽表用定时任务每天凌晨跑一次,数据源就是前三张表。这样领导要的任何统计,都能从宽表里直接查。
6.3 复盘时最有用的三个指标
跑了一段时间后,我发现复盘时真正有用的指标就三个:
- 重复告警率:同一设备同一告警类型在 7 天内触发超过 3 次的比例。这个指标高,说明根因没解决,工单只是“表面关闭”。
- 平均闭环时长:从告警触发到工单归档的时间。这个指标要分告警等级看,P0 和 P2 不能混在一起平均。
- 工单退回率:验收不通过被退回的工单比例。这个指标高,说明处理质量有问题。
这三个指标我后来做成了日报,每天早上自动推到运维主管的 IM 上。说实话,比任何大屏都管用。
7. 把 5 个坑串起来:我的闭环设计检查清单
踩完这 5 个坑,我整理了一份检查清单,每次新项目启动时过一遍。清单不长,但每一条都是用返工换来的:
- 数据接入层:连续量和状态量是否分类处理?是否做了平滑或去噪?采样频率和上报频率是否匹配?
- 规则引擎层:是否有持续时长和冷却时间?是否支持分时段基线?告警等级是否可升级?
- 派工层:是否考虑在班状态和负载?是否有超时兜底?技能标签是否控制在 15 个以内?
- IM 推送层:是否做了聚合去重?消息是否带序列号?操作按钮是否直连工单系统?
- 工单层:状态机是否和告警联动?是否有处理记录?是否有验收环节?
- 数据层:告警和工单是否有关联字段?是否有闭环宽表?是否有重复告警率、平均闭环时长、工单退回率三个指标?
这份清单我放在项目 Wiki 首页,新来的同事第一周就要过一遍。看起来简单,但每一条背后都是一个真实踩过的坑。
最后分享一个我个人的体会:告警闭环的难点从来不在技术,而在“定义清楚什么叫闭环”。是告警消失了算闭环,还是工单归档了算闭环,还是根因消除了算闭环?这三个定义对应三套完全不同的系统设计。我现在的做法是,项目启动时就把这三个定义和运维团队对齐,写进需求文档,后面所有设计都围绕它展开。对齐一次,省掉后面无数扯皮。