有个接入端口的告警响了好几天:邻居一会儿在、一会儿不在,一天几十次。奇怪的是没人报障——业务正常,没丢包,用户甚至没感觉到。
这种「不痛但一直响」的告警其实最烦。真断了反而好办,照着流程查就是了;反复抖、又不影响什么,最容易被人一句「先观察」放过去,然后在监控里一直挂着,把真正要紧的告警淹掉。
第一反应:当成物理问题
端口状态在抖,条件反射就是查物理层。水晶头、线缆、模块、端口本身,按这个顺序来。
我先做了两件事:看端口的错误计数,干净得不像有故障;把线换到同一个设备上的另一个口,观察了一阵。
换口这一步是我觉得最值钱的一个动作,因为结果只有两种,每种都能把范围砍掉一半:
- 故障留在原口 → 问题在本端端口或模块;
- 故障跟着线跑到新口 → 问题在线的另一头,或对端设备。
这次是后者。线换过去,抖也跟着过去了。本端硬件基本可以排除。
到这儿我还没怀疑自己的方向,只是把目标从「本端口」改成了「对端设备」,准备接着查对端是不是接触不良或者在重启。
转折:日志里根本没有链路事件
真正让我停下来的,是坐下来把那几天的日志完整翻了一遍,而不是只看最后刷屏的那一屏。
里面没有一条链路状态变化记录。成对出现的全是邻居表项的删除和新增:某时刻邻居被删掉,过一会儿又重新学到,如此循环。物理层从头到尾是 up 的。
也就是说,那个「Up/Down」是我自己脑补的。告警文案把「邻居消失」简写成了 down,我顺手就把它理解成链路 down,然后按链路故障查了半天。链路状态和邻居表项状态是两码事,前者是物理事实,后者只是一张表里的记录还在不在。
这一步之后,换线、换模块这些动作全白做了。倒也不算亏,至少把本端摘干净了。
所以到底在抖什么
邻居发现协议不是「持续在线」这种概念,它靠周期性报文续期:对端隔一段时间发一次通告,本端收到就刷新一下表项;超过保持时间还没收到,就把这条表项老化删掉。等下一个报文来了,再学一遍。
于是「反复出现又消失」未必是有人把线拔了,也可能只是报文间隔被拉长,超过了保持时间。
对端是台带节能策略的设备,空闲时会进入低功耗状态,发包节奏跟着变慢。慢到超过本端的保持时间,邻居就被删掉;等设备活跃起来,又重新学到。所以抖动有规律、业务不中断、错误计数干干净净——链路一直好好地在那儿,只是那张表在反复过期。
验证也没绕远路:把抖动的时间点和对端的空闲时段对一下,规律基本吻合;再把保持时间放宽观察,抖动就停了。处理办法是让发送间隔和保持时间重新匹配上,或者在那台设备上关掉相关的节能项。自始至终没「修」过任何链路。
这事儿留下的三条
一、先确认告警在说什么,再动手。「Down」是监控平台定义的,不是设备定义的。它描述的是表项、协议状态还是物理链路,得回去看一眼原始日志。替告警补语义,是我在这一步栽的跟头。
二、换口法值得留在肌肉记忆里。故障跟着走就是对端,留在原口就是本端。一个动作、不需要任何工具,就能把排查范围砍一半。
三、规律性的抖动,先找定时器,别找错误。错误计数干净、有固定节奏、不影响业务——这三条凑齐,八成是某个超时或节能机制在作祟,而不是哪里坏了。「坏了」通常是随机的,「配置」才准时。
最后
这类故障没有业务影响,很容易被搁置。但它会一直刷屏,让监控变得不值得信任,等真出事的时候,人已经习惯性忽略那一栏了。所以还是值得花半小时坐下来,把日志从头读一遍。
那半小时里最有用的不是换线,是发现自己把两个「不在了」当成了同一件事。
现在再看到「Up/Down」,我会先问一句:是链路在抖,还是只是一张表在抖。