数据采集停了,怎么第一时间知道?给自动采集加一道“看守”

环保水务数据采集监控告警做法复盘

结论先说: 自动采集最怕的不是报错,而是悄悄停了、没人知道。我在北京环保水务系统上做了三件事:第一,看守程序独立于采集程序运行,采集挂了它照样会响;第二,全系统只用一个“成功”的定义,必须是真正跑完的才算;第三,“覆盖不完整”这种不会报错的问题,也要定期摆到人眼前。

问题:一次“没报错”的停更

系统每个工作日定时去公共资源交易平台翻公告。有一次连续两轮没有新数据,但我没收到任何报警,因为报警逻辑写在采集程序里面,而采集程序在开始干活之前就失败了,报警代码根本没机会运行。

这暴露了一个很普遍的设计问题:让一个程序自己报告自己挂了,是靠不住的。

做法一:看守要独立

现在的看守是服务器上一个单独的定时任务,和采集程序完全分开。它只做一件事:看最近一次成功采集是什么时候。工作日两个检查时间点(08:35、16:35)各看一次,在 45 分钟宽限后核对计划槽,连续两个计划槽都没有新的成功记录才发邮件。

几个细节:

  • 同一次停采只发一封邮件,不会每小时轰炸;
  • 看守只读正式采集数据;告警去重状态另行保存,不修改正式数据;
  • 看守自己也可能挂掉,所以每周一它会发一封运行摘要:正常时明确写“运行正常”,有覆盖缺口时列出需要关注的项。哪周没收到这封信,就要检查看守和邮件链路,不能把沉默当作正常。

做法二:“成功”只能有一个定义

排查时发现一个隐蔽的问题:采集记录在开始时就被标成了“成功”,跑完再补上结束时间。如果程序中途被强行终止(比如超时被系统杀掉),就会留下一条“成功、但没有结束时间”的记录。

更麻烦的是,系统里有两处用到“上次成功”:看守用的是“成功且已结束”,没问题;但计算下次从哪天开始翻页的逻辑只看“成功”两个字。结果就是:看守正确地报了警,但没采到的那段日期已经被当作“采过了”,悄悄漏掉。

修法很简单:

  • 采集开始时先标“运行中”,跑完才改成“成功”;
  • “成功”的判断抽成一个共用函数,两处调用同一个,以后不会再各写各的;
  • 补了测试:故意造一条“成功但没结束”的记录,确认它不会被当成起点。

做法三:不报错的问题,也要让人看见

另一类问题更隐蔽:采集跑完了,没报错,但某个栏目翻到页数上限还没翻完,后面的公告其实没看到。这种情况不会触发任何错误。

我的处理是:每个栏目都记录“翻了几页、为什么停、边界是否完整”,覆盖不完整的情况每周汇总进那封摘要邮件。宁可多一封邮件,也不让“没报错”被误读成“全采到了”。

一次网络超时,要不要大改?

有一轮采集访问交易平台时连续超时,15 分钟后被终止。第一反应是换个地方跑采集,但查了一周的记录:交易平台的连接超时集中在这一轮;另有测试和依赖准备阶段的失败,不能说其余各轮都正常。从服务器另做三次只读连通性测试,均返回成功,但这不能倒推当时故障的唯一原因。

一次异常不足以支撑一次迁移。最后只做了小调整:超时上限从 15 分钟放宽到 30 分钟,告警的等待时间相应延后,避免采集还在跑就误报。之后第一轮自然采集,12 个栏目最多翻了 13 页,全部翻出时间窗口,零错误。

你能拿走什么

  1. 报警不能只写在被监控的程序里。 看守要独立运行、只读正式数据。
  2. “成功”全系统只能有一个定义,而且必须是“真正跑完”,抽成共用函数。
  3. 看守也要被看守。 定期发一封“我还活着”,比什么都不发更可靠。
  4. “没报错”和“覆盖完整”是两回事。 记录边界是否翻完,定期给人看。
  5. 一次异常先观察,不急着大改。 有多次证据再决定是否迁移。

相关作品:北京环保水务产业智能系统