404 not found 的字面意思是服务器收到了请求,但找不到对应资源。真正麻烦的是:当抓取日志记录了一次 404,而应用日志里的同一请求时间相差几分钟甚至几小时,你无法判断这是同一次访问,也就无法确认该 URL 是否应该继续返回 404。对齐事件的关键不是统一时钟,而是先确认两套日志的时间语义是否一致,再决定用请求标识对齐还是用时间窗口对齐。
抓取日志的时间通常是爬虫发出请求或收到响应的时刻,应用日志的时间通常是请求进入应用、开始处理或写入日志的时刻。两者之间可能隔着 DNS、负载均衡、缓存层和队列。如果时间差稳定在某个固定值附近,例如每次都相差三到五分钟,那么更可能是时区或时钟偏移问题。如果时间差随机分布,从几秒到几十分钟都有,那么更可能是链路延迟或日志写入延迟,而不是时钟本身出错。
判断依据可以这样用:随机抽取二十条应用日志中的 404 记录,按 URL 去抓取日志里找同名 URL,比较时间差。如果差值集中在同一方向且波动很小,先处理时区与 NTP 同步;如果差值方向不一致、波动很大,先检查是否有缓存层在替应用返回 404,因为缓存返回的响应不会出现在应用日志里。
当差值稳定,说明两套日志记录的是同一事件,只是基准不同。此时不要急着写脚本做时间偏移补偿,而应先确认服务器、容器和日志采集器是否都使用同一时区,以及 NTP 是否正常同步。一个实际动作是:在应用服务器和抓取入口各执行一次 date -u,比较 UTC 时间是否一致。如果一致,再看日志格式里记录的是本地时间还是 UTC。
修正时钟或统一时区后,重新采集一段时间的日志,再比较同一 URL 的 404 记录。如果时间差收敛到秒级,说明对齐问题已经解决,接下来可以直接用时间加 URL 做关联。如果修正后仍有稳定偏移,那么偏移量本身就是一个线索,说明中间还有一层你没有纳入时间基准的组件。
当时间差没有稳定规律,用时间窗口对齐会非常不可靠。假设你把窗口设为正负五分钟,可能把两次不同的 404 请求误判为同一次;窗口设得太窄,又可能漏掉真正对应的记录。这种情况下,更可靠的做法是寻找两套日志共有的请求标识,例如请求 ID、追踪 ID 或客户端 IP 加 User-Agent 加 URL 的组合。
具体动作是:在应用层为每个请求生成或透传一个请求 ID,并确保该 ID 出现在应用日志中;同时确认抓取入口或反向代理是否把这个 ID 记录到了抓取日志。如果抓取日志拿不到请求 ID,退一步用客户端 IP、User-Agent 和 URL 三者组合做匹配,但要接受同一 IP 在短时间内重复请求同一 URL 时可能产生歧义。
对齐事件本身不是目的,目的是判断 404 是否符合预期。如果对齐后发现该 URL 确实已删除,且没有等价替代页面,那么返回 404 是合理的。如果对齐后发现该 URL 仍然存在,只是应用在某个条件下错误地返回了 404,那么问题在应用逻辑,不在抓取层。
这里有一个常见例外:缓存层返回的 404 不会出现在应用日志里,所以两套日志对不上,未必是时间问题,也可能是其中一套根本没有记录这次响应。遇到这种情况,先确认 404 是由应用产生还是由缓存或网关产生,再决定是否需要清理缓存规则。robots.txt 的抓取限制不等于可靠的索引移除,站点地图也不保证收录,所以不要用这两者来替代对 404 本身的判断。
假设某站点在 10:00 的抓取日志里记录了对 /old-page 的 404,而应用日志里同一 URL 的 404 出现在 10:07。如果连续多天差值都在七分钟左右,优先检查时区和 NTP;如果差值每天不同,优先检查是否有 CDN 或反向代理在应用之前返回了 404。这个例子只用于说明比较方法,不代表任何真实站点的实际数据。
对齐事件时,先确认时间语义,再根据差值是否稳定选择修时钟还是改用请求标识。对齐成功后,再判断 404 是预期删除还是应用错误,这一步决定你下一步是改应用逻辑还是调整缓存规则。