☰
离线告警规则引擎在小程序中的设计与实践:基于CodeArts AI智能体
2026/10/26 6:24:01 网站建设 项目流程

这么多年做运维工具,我有个很深的体会:告警规则引擎这类东西,听起来是后端服务的活儿,一旦落到「运维巡检小程序」这种场景里,真正的难点根本不是规则的编写,而是规则引擎在脱离云端之后,还能不能独立、稳定、正确地跑起来。这次我基于华为云 CodeArts 的 AI 智能体,把整套离线告警规则引擎从设计到落地完整做了一遍,规则解析、阈值判定、状态收敛、离线缓存与补报全都放在了小程序本地,实测下来这套方案在弱网和彻底断网的巡检场景下都能稳定工作,值得把完整的思路和代码细节整理出来分享给做运维工具、做 IoT 边缘巡检、做小程序开发的朋友们。

这次项目最核心的一个决策,是把「告警判定」从云端下沉到了小程序本地。巡检人员下到机房、地下车库、弱电井这些信号死角的时候,手机经常处于断网状态,如果告警规则只能靠云端接口才能判断,那断网期间发生的指标异常就会彻底漏掉,等巡检人员走出死角再上报,故障可能已经持续了几个小时。所以我把规则引擎做成了纯本地模块:小程序启动时从服务端拉取最新的告警规则,缓存到本地存储;巡检过程中采集到的各项指标直接走本地规则匹配,命中后立即触发告警动作;告警记录先写入本地队列,等网络恢复后再批量补报到后端。这套逻辑跑下来,即使全程离线,告警的发现、判定、提醒一条链都不会断。

1. 项目全貌与技术选型:为什么用 CodeArts + AI 智能体搭规则引擎

1.1 这次要解决的真实痛点

先说说业务背景。运维巡检小程序的典型使用场景是:巡检人员按计划走到指定的设备点位前,对着设备扫码或者手动选择设备,然后录入或者自动采集一组运行指标,比如 CPU 使用率、内存占用、磁盘剩余空间、网络延迟、服务存活状态等等。正常情况下,这些指标录入后就提交到云端,由云端规则引擎判断是否需要告警。

这个模式有个天然缺陷:它假设了「巡检人员必须在有网的环境下工作」。可实际情况是,很多需要巡检的设备恰恰部署在网络盲区里。我接手过的项目里,有人在地下车库的配电房做巡检,有人在厂区偏僻角落的弱电井做巡检,还有人直接在隧道里做设备巡查,这些地方要么 4G/5G 信号弱到几乎不可用,要么干脆就是信号死角。巡检人员如果依赖云端告警,在断网区域采集的数据就只能干等,等走出盲区再提交,中间这段时间内的异常指标完全没有被识别。

另外一个痛点在于告警规则的时效性。传统做法里,规则变更要经过「修改规则-部署后端-发布服务」的完整流程,一个规则从提需求到真正生效,最快也要半天。对于巡检项目来说,某些临时性告警需求(比如今天重点关注某台设备的磁盘增长趋势、某条线路的延迟波动)根本等不起这个周期。把规则引擎下沉到小程序本地后,规则变更只需要更新小程序端缓存,甚至可以做到分钟级生效。

1.2 为什么规则引擎必须离线运行

我设计的离线告警规则引擎,核心思路是把「规则的执行能力」完整放在小程序本地。这里的「离线」不是指完全不联网,而是指规则引擎在断网环境下依然具备完整的规则匹配、阈值判断、告警触发和本地记录能力。

对比一下在线和离线两种方案就清楚了。在线方案的问题是单点依赖:规则引擎依赖网络请求,网络一断,告警判断立刻失效;规则引擎依赖云端服务可用性,后端服务一抖动,告警延迟就飙升;规则引擎依赖请求响应时间,巡检人员在弱网环境下可能要等几十秒才收到判断结果,操作体验很差。离线方案则是把规则数据和规则执行引擎都内嵌到小程序里,启动时只需要一次规则同步,之后所有判断都在本地毫秒级完成,不产生任何网络开销,也不受网络质量影响。

有人会担心离线方案的好处是不是靠牺牲「规则灵活性」换来的,其实这是一个误区。规则引擎的灵活性取决于规则描述语言的设计,而不是取决于规则引擎部署在哪里。你在本地用 JSON 描述一条规则,和在云端用 JSON 描述一条规则,表达能力是完全一样的。本地规则引擎反而因为不需要考虑网络序列化和传输开销,可以支持更复杂的复合条件和多规则叠加。

1.3 AI 智能体在项目里的真实定位

这个项目里我用了华为云 CodeArts 平台上的 AI 智能体来做辅助开发,它在整个流程里的角色更像一个「熟悉规则引擎设计的老同事」,而不是一个简单的代码生成器。

AI 智能体在这个项目里干了三件事:第一,帮我梳理规则引擎的数据模型。我告诉它巡检场景的指标类型和告警需求后,它很快给出了一版规则数据模型草案,包括规则 ID、规则名称、监控指标、比较操作符、阈值、时间窗口、连续触发次数等字段,这个草案比我自己从零开始设计要完整得多,省掉了很多反复修改的来回。第二,帮我生成规则引擎的核心代码骨架,包括规则解析器、规则匹配器、告警触发器和本地存储封装,这一部分我用自然语言描述需求,它直接产出可运行的 TypeScript 代码,我再针对业务场景做调整。第三,帮我写测试用例。它根据规则模型自动生成了一批边界测试数据,比如临界值、空值、异常格式的指标数据,这些用例帮我提前发现了不少规则边界问题。

需要强调的是,AI 智能体产出的代码我不会直接上线,每一行都会过一遍评审,重点检查安全边界、异常处理和资源释放。在 CodeArts 平台里,AI 智能体的代码建议和我的审查修订可以形成很好的协作闭环:它出初稿,我改逻辑,改完再丢回给它做 code review,来回几轮之后代码质量提升非常明显。

2. 规则引擎的核心设计:可离线判断的告警逻辑长什么样

2.1 规则输入数据的建模:先定义清楚「一条记录」长什么样

任何规则引擎,第一步都是确定输入数据的结构。在这个项目里,规则的输入是一条「巡检指标记录」,我用 TypeScript 接口定义如下:

interface MetricRecord { deviceId: string; // 设备唯一标识,比如 "UPS-001" deviceName: string; // 设备显示名称 location: string; // 点位位置,比如 "B2-配电房-03号柜" metricType: string; // 指标类型:cpu / memory / disk / latency / status metricValue: number; // 指标数值。status 类型时约定 1=在线,0=离线 unit: string; // 单位:% / MB / GB / ms collectedAt: number; // 采集时间戳(本地 epoch 毫秒) online: boolean; // 网络状态:是否在线 }

这里有个容易忽略但很重要的字段是online。它表示的是「采集当时小程序所处的网络状态」,而不是设备的在线状态。这个字段在离线方案里特别有用:当online=false时,说明这条记录是在断网情况下采集的,规则引擎判断命中告警后,告警记录的投递方式要走离线队列;当网络恢复后,补报逻辑也要依赖这个标记来区分告警是实时产生的还是补报产生的。

刚开始设计的时候我没有加collectedAt这个字段,后来发现这是一个失误。小程序的new Date()获取的是用户手机的本地时间,如果用户手机时间不准,告警记录的时间戳就会出现偏差。而且离线期间产生的告警,补报时云端并不信任小程序的本地时间,必须用记录里的collectedAt上报并校验。所以collectedAt必须由采集逻辑显式写入,不能用规则引擎执行时的系统时间替代。

再补充一点:实际项目中巡检采集往往是一次采集得到多条指标(同一台设备同时采集 CPU、内存、磁盘等多个指标),所以数据层做了一个简单的批次拆分——把一次巡检采集的MetricRecord[]数组拆成单条记录逐条送进规则引擎。这个拆批逻辑放在采集端做,规则引擎本身只处理单条记录,这样做的好处是规则引擎的状态管理会简单很多,也方便单条单元测试。

2.2 规则表达式的定义:让非开发人员也能看懂告警条件

告警规则引擎的第二个核心是规则描述语言。我不打算设计一门全新的 DSL,而是在 JSON 的基础上做了一套结构化的规则描述规范,用嵌套字段的方式表达「在什么条件下、持续多久、触发什么级别的告警」。

规则的基础结构如下:

{ "ruleId": "R001", "ruleName": "CPU使用率过高告警", "description": "CPU使用率连续3次超过90%时触发", "enabled": true, "metricType": "cpu", "condition": { "operator": ">", "threshold": 90, "windowCount": 3 }, "severity": "critical", "actions": ["localNotify", "webhook"], "cooldownSeconds": 300 }

其中condition表达核心判定逻辑:metricType指定这条规则监控哪种指标,operator是比较操作符(支持>、>=、<、<=、==、!=),threshold是阈值,windowCount是连续触发的次数要求。这个windowCount是我反复权衡后保留的关键设计:单次指标超阈值并不能说明设备有问题,可能是瞬时抖动,但连续 N 次超阈值就基本可以确认异常了。

操作符的语义要定义清楚。>表示「指标值大于阈值」,>=表示「大于等于」,字符串类型的指标(比如设备状态status)用==和!=来判断。最初设计时我还考虑过支持正则表达式,但评估后放弃了——正则表达式的计算开销在小程序本地执行会增加不少耗时,而且巡检指标绝大多数是数值型,匹配字符串的场景极少,没必要为一个低频场景引入复杂度。

还有一个重要设计是cooldownSeconds,冷却时间。它的作用是防止告警风暴:同一个规则命中的告警在冷却时间内不会重复触发。比如冷却时间 300 秒,那么该规则首次触发告警后,5 分钟内即使持续命中也不会再产生新的告警记录,直到冷却期结束并且指标回落到正常范围后再次超阈值,才会触发新一轮告警。这个机制在实际运维中非常实用,不然断网点位一次持续性的故障,会把告警记录刷爆。

为了增强规则的表达能力,我额外支持了condition的复合结构——用and或or组合多个条件。比如「磁盘使用率超过 85% 且剩余空间低于 20GB」才算告警:

{ "ruleId": "R002", "ruleName": "磁盘空间不足告警", "enabled": true, "metricType": "disk", "condition": { "logic": "and", "subConditions": [ { "metricType": "disk", "operator": ">", "threshold": 85, "unit": "%" }, { "metricType": "disk_free", "operator": "<", "threshold": 20, "unit": "GB" } ], "windowCount": 2 }, "severity": "warning", "actions": ["localNotify"], "cooldownSeconds": 600 }

复合条件的解析比简单条件复杂一些,但实现上也不难——递归解析subConditions数组,先求每个子条件的布尔结果,再用and/or合并。我在设计时有一个原则:规则尽量扁平、尽量少嵌套,嵌套层级超过两层的规则,可读性会急剧下降,也不利于非开发人员维护。AI 智能体在生成规则解析器的时候,默认用了递归下降的思路,正好和这个分层结构匹配。

2.3 状态记忆与告警判定:离线引擎的关键在于「记住过去」

规则引擎要有状态。这个「状态」就是我前面提到的windowCount要用的历史命中记录。在线方案里,状态可以放在 Redis 里,每次判断都去查。离线方案就不行了,状态必须放在小程序本地。

我给规则引擎设计了一个轻量级的状态存储,用wx.setStorageSync实现了一个简单的 KV 存储封装,每条规则维护一个「最近命中计数」:

class RuleStateStore { private prefix = 'rule_state_'; get(ruleId: string): number { const key = `${this.prefix}${ruleId}`; const val = wx.getStorageSync(key); return typeof val === 'number' ? val : 0; } increment(ruleId: string): number { const next = this.get(ruleId) + 1; wx.setStorageSync(`${this.prefix}${ruleId}`, next); return next; } reset(ruleId: string): void { wx.setStorageSync(`${this.prefix}${ruleId}`, 0); } }

状态更新的逻辑不复杂:每进来一条记录,先用规则解析器判断这单条记录是否满足条件;如果满足,increment之后判断连续命中次数是否达到windowCount,达到就触发告警;如果不满足,reset清零。仔细看会发现这其实是一个滑窗的简化实现——真正的滑动窗口需要记录每次命中的时间戳,然后只统计最近 N 分钟内的命中次数,但为了在小程序本地尽量降低存储和计算开销,我选用了「连续命中计数」方案,语义上略有差异,但在实际巡检场景下足够可靠。

这里有个细节值得展开:连续命中计数和滑动窗口在什么情况下会产生差异?假设规则是「CPU 连续 3 次超过 90%」,如果巡检记录序列是:超阈值、超阈值、不超、超阈值、超阈值、超阈值。连续计数方案下,第 6 条记录命中时计数到 3,触发告警;而滑动窗口方案统计的是最近 6 条里有没有 3 次超阈值,也会触发。真正的差异出现在穿插次数较多的情况下,比如 3 次超阈值中间隔了 2 次正常记录。连续计数不触发,滑动窗口触发。对于运维巡检场景,设备异常通常会持续,而不是震荡式地偶发,所以连续计数反而能过滤掉更多抖动带来的误报。我把这个差异点写进了设计文档里,让业务方能按需选择规则语义。

触发告警后,告警记录立刻写入本地告警队列,队列结构就是一个数组,保存在本地存储中:

interface AlertRecord { alertId: string; ruleId: string; ruleName: string; deviceId: string; deviceName: string; metricType: string; metricValue: number; threshold: number; severity: string; triggeredAt: number; // 触发时间(本地时间) collectedAt: number; // 采集时间(来自输入记录) acknowledged: boolean; synced: boolean; // 是否已同步到云端 }

synced字段是专门为离线补报设计的:网络正常时,告警记录产生后立即同步云端,synced标记为true;断网时先写入本地队列,synced保持false。等网络恢复后,同步模块扫描本地队列,把所有synced=false的记录逐条上报,上报成功后翻转标记。这样即使一次故障产生了几百条告警,也不会因为网络问题丢失任何一条。

告警触发后的动作执行分两层:第一层是本地动作,包括小程序内的振动提醒、本地通知、巡检页面的红点标记;第二层是远端动作,通过 Webhook 把告警推送到企业微信、钉钉或者自有运维平台。远端动作在断网时自动跳过,等补报时再统一触发或者由云端负责通知。

3. 基于 CodeArts 的实战落地:从对话式需求到可运行代码

3.1 用 AI 智能体生成规则引擎骨架

前面聊了比较多的设计思路,现在讲讲实际的开发过程。整个开发我是基于华为云 CodeArts 完成的,AI 智能体在这个过程中确实帮了大忙,特别是写代码骨架和单元测试这两块。

第一步是让 AI 智能体理解规则引擎的数据模型。我是用自然语言描述需求的,大致意思是:「我要在微信小程序里实现一个离线告警规则引擎,输入是设备指标记录对象,包含 deviceId、metricType、metricValue、collectedAt 等字段;规则用 JSON 描述,包含条件、阈值、连续触发次数、冷却时间;规则命中后生成告警记录并写入本地队列;请帮我设计核心数据结构和匹配逻辑。」AI 智能体很快就返回了一版代码骨架。

它生成的版本里有几个亮点。一个是规则匹配器用了策略模式,把不同的操作符(>、>=、<等)抽象成独立的比较函数,后续要新增操作符只需要扩展策略集合,不用改动主流程。另一个是它自动加了severity级别的排序逻辑,告警记录按严重程度排序写入队列,紧急告警排前面,避免低级别告警阻塞高级别告警的处理。这个细节最初我没想到,但它加得很合理。

不过它生成的代码也有一个明显问题:没有处理小程序的存储限制。wx.setStorageSync有单个 key 的大小限制(iOS 和 Android 各不相同),如果告警记录数量多了,直接塞一个数组到同一个 key 里,迟早会擦到存储上限。我把它生成的数据持久层改写成了「按天分片存储」的版本,每天一个 key 存当天的告警记录,再维护一个索引 key 记录哪些天有数据。这个改动避免了单 key 存储过大的问题,补报时也能按天分批读取,更加可控。

AI 智能体的生成只是第一步,集成、调整、补逻辑才是重头戏。它给我提供了一个好的起点,但真正让它适配业务场景,靠的还是我们之间的交替修改与评审。

3.2 规则接入与巡检采集:跑通「采集-匹配-告警」主链路

规则引擎的核心模块有了之后,下一步是把它接到小程序的巡检流程里。巡检的主流程是这样的:巡检人员在小程序里选择点位,进入巡检页面,页面上展示该点位需要检查的若干检查项;巡检人员按检查项依次操作(手动录入数值、扫描设备读取参数、或者通过蓝牙/串口拿到设备状态);每个检查项完成后生成一条MetricRecord,送入规则引擎。

这里有一个关键点:规则引擎的触发时机应该尽量靠前。我最初的版本是在巡检页面全部填写完成后,统一把一批记录送到规则引擎去判断,后来实测发现一个体验问题——如果巡检人员填了 20 个检查项,第 5 项就已经触发严重告警了,但界面一点提示都没有,他得把后面 15 项全部填完才能看到告警提示。这不合理,也不符合运维场景对「即时反馈」的要求。

调整后的方案是:每完成一个检查项,就立即把该检查项对应的MetricRecord送入规则引擎,命中告警时马上在当前巡检页弹出告警浮层,同时让该检查项的状态显示为异常。这样巡检人员当场就能发现异常并确认设备实际状态,可以现场二次核实或者拍照留证。这是离线规则引擎带来的额外优势——在线方案里每填一项都要等网络往返,根本不可能做到这样流畅的实时反馈。

接入过程中我遇到的一个典型问题是规则引擎被重复初始化。因为小程序的页面可能被多次加载,每次加载如果都重新初始化规则引擎,就会重复注册状态存储和定时器,导致同一份规则被执行两次,产生重复告警。这个问题排查了很久,最终用了一个全局单例模式,把规则引擎实例挂在小程序的getApp()全局对象上,页面销毁时不销毁引擎,只在应用退出时清理。这算是一个比较经典的微信小程序全局状态管理问题,但结合规则引擎的状态性,影响会更大——告警记录一旦重复,补报就会重复,后端去重逻辑也得跟着加。

3.3 规则下发、本地缓存与云端补报:离线方案的最后一环

规则引擎跑在本地,不等于规则就永远不变了。日常运维里规则需要调整:阈值变了、新设备有新的告警规则、某条规则临时要停用。这些都是很常见的需求,所以必须有「规则云端下发、小程序本地缓存」的机制。

我在服务端维护了一份规则配置文件,用版本号标识(比如rules_v3.json)。小程序启动时,先请求/api/rules/latest,把返回的最新版本号跟本地缓存的版本号对比,不同则重新拉取规则并覆盖本地缓存。这个「启动时拉取」的方案在弱网环境下有一个额外的保护——如果拉取失败,程序会保留本地已有规则继续运行,不影响本次巡检任务。

实际运营中还出现过一个规则维护问题:规则文件直接让人手动编辑 JSON,出错率太高。比如有人会把英文逗号和中文逗号混用,直接导致 JSON 解析失败;有人会把阈值单位搞错,把本来应该是 85(%)的写成 0.85。后来我在管理端做了一个简单的表单编辑页,用下发的规则模板来生成 JSON,人为编辑错误大幅减少。这个经验也分享给做规则引擎的朋友:规则引擎的用户界面和规则引擎本身同样重要,没有好用的规则编辑入口,再灵活的规则引擎也会被抱怨「不好用」。

补报逻辑是这个方案的最后一环。网络恢复后的补报,我用了一个简单的监听器:监听wx.onNetworkStatusChange,当网络状态从离线变为在线时,触发一次补报任务。补报任务扫描本地告警队列,把所有synced=false的记录分批上报(每批 20 条,避免一次性大量请求造成服务端压力),上报成功后逐条翻转synced标记。如果上报失败(比如服务端返回 500),则保持synced=false,等下一次网络切换或者应用重启时再次重试,同时连续失败超过 3 次的记录会标记一个syncFailed=true,在管理端页面上显示红色告警,提示人工介入处理。

补报需要考虑数据时序问题,也就是云端不能简单地把补报记录当成实时记录来处理。我实现的方案是:云端补报接口接收告警记录时,以记录里的collectedAt和triggeredAt字段为准,而不是以服务端时间为准。这样补报完成之后,运维平台的告警时间线才和现场巡检的实际时间一致,不会出现「明明下午 2 点发生的故障,因为 5 点才补报成功,告警时间显示成 5 点」这种混淆。

4. 踩坑记录与问题排查实录:离线巡检场景下的典型故障

4.1 时钟偏差问题:手机时间不准导致告警时间错乱

这个坑我是在测试阶段发现的。测试人员在模拟离线场景时,故意把手机时间调快了 10 分钟,结果补报后云端显示告警发生在未来的某个时间点,看起来非常奇怪。进一步排查发现,规则引擎内部判断冷却时间时,直接用了Date.now(),而Date.now()依赖的是手机本地时间,手机时间一不准,冷却判断也全乱了。

解决方案分三层:第一层,采集数据的时间戳collectedAt尽量不依赖手机本地时间,优先使用设备端时间或者服务端下发的时间戳基准;如果确实只能用本地时间,那至少要判断本地时间的合理性——比如与距最近一次服务端时间同步的差值,超过 5 分钟就可以认为本地时间不可信,在告警记录里加一个timeTrust=false的标记,提醒云端审查。第二层,冷却时间的判断改用单调递增的计数器或者相对时间计算,不直接用绝对时间戳。第三层,所有补报记录上报时带上localTimeOffset字段,让云端知道这条记录的本地时间与标准时间的偏差,便于修正。

这算是离线规则引擎特有的问题,在线方案里服务端时间统一,基本不会遇到。提出来是希望大家在实现本地规则引擎的时候,从一开始就把时间一致性作为一个独立的设计点来对待。

4.2 AI 智能体生成代码的边界校验缺失

AI 智能体生成的代码质量整体不错,但边界处理确实需要人工补全。我遇到最典型的一个问题是:它生成的分页读取告警队列的逻辑,只处理了「数组为空」的情况,没处理「数组元素为空对象」「数组某一项损坏导致 JSON.parse 失败」的情况。微信小程序的本地存储,理论上其他逻辑也可能向同一个 key 写入脏数据,一旦解析失败,整个补报任务直接崩溃,而且会阻塞后续所有告警上报。

我给它补了一个健壮的读取封装:每次读取本地存储时,先尝试JSON.parse,失败就返回空数组而不是抛异常;数组里的每一项单独做类型校验,ruleId、deviceId、metricValue等关键字段缺失或类型不对的,直接标记为脏数据移到隔离区,不影响其他数据的处理。这类防御性编程在云端可能只是「锦上添花」,在端上(小程序里)就是「保命」——你根本不知道用户的手机上前一次运行残留了什么脏状态。

同样的问题也出现在规则文件的解析上。AI 生成的规则解析器直接用JSON.parse(rulesText),如果后台回传的规则 JSON 格式错误,小程序端就会在启动时崩溃。我改为:先校验规则文件版本号,再做 JSON 解析,解析失败时保留上一次成功加载的规则,同时上报一个规则解析错误日志到后台。宁可让旧规则多跑一天,也不能让新规则把整个小程序搞崩。

4.3 告警风暴抑制:规则冲突与合并冗余告警

告警风暴是运维场景的老问题,离线场景会让这个问题更严重。因为离线期间告警记录都在本地,无法实时联动云端做收敛,如果规则设计不当,一次设备故障就能产生几十上百条重复告警,补报的时候全部堆到云端。

抑制策略我做了几层。第一层就是前面提到的cooldownSeconds,这是最基础的频率限制。第二层是相似告警合并:同一台设备同一条规则在cooldownSeconds内多次触发的告警,只保留第一条和最后一条,中间的过程信息合并成一个repeatCount字段,避免刷屏。第三层是设备维度收敛:同一设备在同一巡检批次内触发的多条不同规则的告警,在小程序端汇总成一条「设备异常报告」,把各条规则命中的指标、阈值、实际值都列出来,让巡检人员先看汇总,再按需展开详细内容。

这样做的效果非常明显。我实测过一个模拟场景:一台设备磁盘持续增长,5 分钟内连续触发了 20 次「磁盘空间不足」告警,不收敛的话要补报 20 条记录;收敛之后,只有 2 条记录——第一条表示开始异常,第二条表示冷却期后确认持续异常,附带repeatCount=20。云端收到的告警量直接降了一个数量级,后续再对接告警通知渠道也轻松得多。

4.4 小程序性能与规则引擎执行耗时的取舍

规则引擎跑在小程序本地,性能是个不可回避的话题。我最初实现的时候没太在意,因为单条规则匹配的耗时理论上只有几十微秒。但在真机上实测,规则数量稍多一些、每条记录进来都要遍历全部规则,而且规则的复合条件还要递归解析,在低端安卓机上明显感觉到卡顿。

我做了两个关键优化。第一个是预先编译规则:小程序启动时把 JSON 格式的规则解析成内存对象,并按照metricType建立索引——进来的记录直接定位到需要匹配的规则子集,而不是无序遍历全部规则。第二个是延迟处理告警动作:告警记录写入队列后,UI 提示不阻塞主流程,而是通过wx.nextTick或者 setTimeout 延后到下一次事件循环执行,避免在采集过程中打断用户操作。

实测结果:在红米 Note 这样的低端机上,50 条规则、每条记录匹配耗时从最初的 15 毫秒左右降到了不到 3 毫秒,完全无感知。所以给做端侧规则引擎的朋友一个建议:不要迷信「规则引擎一定很重」,只要做好索引和预编译,几百条规则在端上跑是完全没有问题的。

5. 结语与后续扩展建议

这个离线告警规则引擎上线后,巡检人员在信号盲区的作业体验提升非常大:以前断网等于告警失灵,现在断网照样能及时发现异常并在现场处理;后台运维人员也省心了,以前经常接到「我报了故障但系统没收到」的反馈,现在告警不丢、可补报、可查状态,整个链路清晰很多。从 CodeArts 的使用角度来说,AI 智能体在这个项目里确实是合格的协作搭档——设计梳理做得快、代码生成质量可靠、测试用例补得全面,但离线的防御性编程、数据一致性、告警收敛这些工程细节,还是得靠人工经验和反复实测去补完。

另外有几个基于这次实践的小建议。规则引擎的日志一定要完整:每次规则加载、规则匹配命中、告警触发、补报成功或失败,都要记录日志,方便事后排查。巡检场景的规则配置一定要可视化:非技术的运维人员不可能直接写 JSON,表单化的规则管理界面值得优先投入。测试阶段一定要覆盖断网与恢复的全流程:不能只测在线状态下的规则匹配,要专门设计「断网-采集-告警-恢复-补报」的端到端测试用例,光凭真机随便点点,很难暴露时间和队列方面的问题。

接下来我打算在现有引擎上扩展两个方向。一个是往规则里加入简单的预测逻辑:比如根据磁盘近几次采集的增长速率,预估几小时后是否会触达阈值,提前给巡检人员一个预警。另一个是把规则配置做成分级权限管理:部分只读规则由运维平台统一管理,部分自定义临时规则允许现场巡检组长在小程序里直接配置。这样既保证了规则的规范性,又保留了现场处置的灵活性。离线规则引擎这东西,一旦跑通了,你可以加的能力远比你想象得要多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询