去年冬天一个凌晨,我被电话叫醒。某边缘数据汇聚服务每隔几小时就会混进一批本该被拦截的客户端上报数据包,导致下游统计指标出现毛刺。这套服务运行了快半年,白名单过滤逻辑上线时压测、灰度都过了,按道理不该在深夜出这种幺蛾子。
更让人发毛的是:故障无法稳定复现。白天手动断开客户端、重连、抓包,一切正常;可到了凌晨低峰期,日志里就会出现几条“来源标识不在白名单里”的记录,但数据已经落库了。团队里有人怀疑是并发写入导致的竞态,有人猜是内存踩踏,查了两天毫无头绪。
后来我在一次偶然的断网演练中,把客户端所在网段的网关重启了一下,故障瞬间复现。那一刻我才意识到,问题根本不在过滤逻辑本身,而在于重连时连接对象的重建过程——白名单校验用的上下文,和实际数据通道用的上下文,在重连窗口期发生了错位。
踩坑现场:一次网关重启引发的“漏网”
先交代一下这套服务的简化架构。它监听一个固定端口,接受若干采集端的长连接。每个采集端上线时,会先发一个注册帧,里面带一个来源标识字符串。服务端收到注册帧后,查内存里的白名单集合,命中才允许后续数据帧通过;不命中就立刻断开。
白名单集合在服务启动时从本地文件加载,运行期不变。过滤逻辑写在一个状态机里,大致长这样:
// 简化后的状态机片段typedefenum{