上个月一个做金融投放的团队找到我,说他们的分流系统出现了个怪现象:日志里明明记录了某条规则命中,访客却停在默认页没跳走。他们一开始怀疑是302状态码被浏览器缓存了,查了两天没结果。后来把规则链的执行日志拉出来逐条比对,才发现是前一条过滤规则把动作字段覆盖成了空值。规则链动作覆盖冲突不像条件优先级冲突那样容易从命中顺序上看出来,它藏在动作执行层,排查方向不对就会一直绕圈。
动作覆盖冲突和条件冲突的区别
条件冲突是两条规则都满足命中条件,系统按优先级选一条执行,结果可预期。动作覆盖冲突不一样:规则A先执行,写入了某个动作字段;规则B随后也执行,但它的动作配置是空的或默认值,把规则A写入的动作覆盖掉了。最终访客收到的响应里没有任何跳转指令。
这类问题有两个特征。一是命中日志正常,每条规则的命中记录都在,看不出异常。二是动作执行日志里,同一条请求的动作字段被写了多次,最后一次是空值或默认动作。排查时如果只看命中日志,会一直找不到原因。
哪些配置容易触发覆盖
- 过滤型规则的动作字段没显式设为“不操作”,系统按默认值处理,默认值恰好是空动作
- 多条规则共享同一个动作槽位,后执行的规则没判断槽位是否已被写入
- 规则链的短路开关被关闭,所有规则顺序执行而不是命中即停
从动作执行日志定位覆盖点
定位覆盖点需要打开动作执行日志,不能只看命中日志。动作执行日志一般记录三个字段:请求ID、执行到的规则ID、当前动作槽位的值。
操作路径是这样的:
- 取一条跳转失败的请求ID,在动作执行日志里过滤出这条请求的全部记录
- 按时间顺序排列,看动作槽位的值在哪一步被改成了空
- 找到那一步对应的规则ID,检查它的动作配置
- 确认这条规则是过滤型还是决策型,过滤型规则不应该写动作槽位
有个细节容易忽略:部分系统的动作槽位是共享内存,规则并发执行时写入顺序不确定,日志里的顺序可能和实际执行顺序不一致。遇到这种情况,把规则链改成串行执行再复现一次,就能拿到确定的顺序。
动作链审计:把每条规则的动作意图标出来
与其等出问题再排查,不如定期做动作链审计。做法是把规则链里每条规则的动作意图列出来,标注三类:
- 只读型:只判断条件,不写任何动作字段
- 写入型:会写入跳转目标、状态码等动作字段
- 覆盖型:会清空或重置动作槽位
审计的目标是确认过滤型规则全部归入只读型。如果发现某条过滤规则被标成了覆盖型,要么改配置,要么调整它在链中的位置,让它排在所有写入型规则之前。
审计频率建议跟规则库更新节奏绑定。规则库每次热更新后跑一次审计脚本,把动作意图和上次的审计结果做diff,新增的覆盖型规则要人工确认。
修复后的回归验证
改完配置不能只看单条请求是否跳转成功,要做回归验证。
验证分两层。第一层是单请求回放:取之前跳转失败的请求ID,用日志回放工具重跑,确认动作槽位不再被覆盖。第二层是批量验证:从最近一天的请求日志里随机抽一批,统计跳转成功率,和修复前的基线对比。
批量验证时要注意,跳转成功率的基线不能只看总体数字。按规则链分支拆开看,如果只有某条分支的成功率回升,其他分支没变化,说明修复范围可能不够。
有个客户修复后总体跳转成功率从九成出头回到了九成八,但拆开看发现有一条分支还是没变化,原因是那条分支用了独立的动作槽位,没被这次修复覆盖到。后来把两条分支的动作槽位配置统一了才彻底解决。
小结
规则链动作覆盖冲突的排查关键在动作执行日志,不在命中日志。定位到覆盖点后,通过动作链审计把过滤型规则和写入型规则分开,再做单请求回放和批量验证确认修复效果。日常运维中把动作链审计和规则库热更新绑定,能提前拦住大部分覆盖问题。
常见问题
动作覆盖冲突会导致跳转请求完全没响应吗
不会完全没响应,访客会收到页面,只是收到的是默认页或兜底页。从访客角度看就是没跳转,从系统角度看请求正常处理完了,只是动作字段被清空了。
为什么命中日志里看不出动作覆盖的问题
命中日志只记录哪条规则命中了,不记录动作槽位的变化过程。要定位覆盖问题得看动作执行日志,它才记录每次动作字段的写入值。
过滤型规则一定会覆盖动作吗
这个要看情况。如果过滤型规则的动作配置是“不操作”,就不会覆盖。只有配置里显式或隐式地写了空动作,才会覆盖已有的动作槽位。
动作链审计需要多久做一次
建议跟规则库更新节奏绑定,每次热更新后跑一次。如果规则库更新不频繁,至少每周做一次全量审计。顺带说一句,我一般还会在审计脚本里加个告警,新增覆盖型规则时直接通知到人。
修复后回归验证只看跳转成功率够吗
不够。跳转成功率是总体指标,可能掩盖分支级别的差异。建议按规则链分支拆开看,每个分支的成功率都回到基线才算修好。
延伸阅读
本文聚焦动作覆盖冲突的排查与修复,如果你想从更完整的AB页跳转配置视角理解规则链与动作槽位的整体设计,下面这篇教程从原理到实战配置都做了系统梳理,可作为本文的补充阅读。