长等待任务别在会话里干等:把状态外置成检查点

举报
yd_213533429 发表于 2026/11/09 12:45:27 2026/11/09
【摘要】 长等待任务别在会话里干等:把状态外置成检查点定时任务跑久了会撞上一个很隐蔽的问题:动作本身都成功了,但等到你想回头核对结果时,执行环境已经没了。这篇记录一次真实的会话回收事故,以及后来改成检查点式核对的做法。## 一、现象:延迟核对把自己等没了有个任务提交后大约八分钟才结算,所以我在脚本末尾加了一段等待,打算先读一次积分,睡八分钟,再读一次,比较两次差值得出结论。第一次读很顺利,数据正确。第...

长等待任务别在会话里干等:把状态外置成检查点


定时任务跑久了会撞上一个很隐蔽的问题:动作本身都成功了,但等到你想回头核对结果时,执行环境已经没了。这篇记录一次真实的会话回收事故,以及后来改成检查点式核对的做法。


## 一、现象:延迟核对把自己等没了


有个任务提交后大约八分钟才结算,所以我在脚本末尾加了一段等待,打算先读一次积分,睡八分钟,再读一次,比较两次差值得出结论。


第一次读很顺利,数据正确。第二次读直接报了个空引用异常:创建标签页的方法返回了空值。继续查才发现会话已经被回收了,报错信息里写得很清楚:默认五分钟闲置就关闭会话,窗口和它打开的所有标签一起清掉。


也就是说,睡眠那八分钟里,会话本身先一步超时了。脚本还以为自己在一个活着的浏览器里工作。这是典型的"等待的对象和执行的对象不是同一个东西"。


## 二、为什么简单的重试没用


第一反应是加重试:捕获空值,重新创建标签页再读一次。结果仍然报"会话未注册或已停止"。


原因是回收发生在会话层,不是标签层。标签页是会话的子资源,父资源没了,子资源自然也重建不出来。任何在同一个会话上下文里的重试都必然失败。这种失败靠重试循环解决不了,只能换执行载体。


还有一层容易忽略:等待期间没有任何浏览器交互。很多自动化框架把"闲置"定义为没有动作命令,睡眠不算活动,于是计时器一路走到阈值。这不是超时设置太短的问题,是任务形状与框架生命周期模型不匹配。


## 三、改成检查点:把状态外置


新的做法是让等待发生在新会话之外,每一步自带完整的初始化:


1. 第一步只做动作和一次即时读取,把结果(总分、明细行、时间戳)写进本地文件,然后正常关闭会话。

2. 等待交给外层调度,或者干脆等下一次触发时再跑。

3. 第二步启动时新建会话,重新走一遍初始化,读同一份外置文件做基线,再取当前数据与基线比较,得出增量。


关键变化是:核对逻辑不再依赖"上一次那个还活着的浏览器"。所有跨时间需要保留的东西都落在文件里,会话变成一次性的、可丢弃的执行槽。这样即使中间隔了十分钟、一小时,或者机器重启过,比较仍然成立。


代价是每次都要重新初始化,多花十几秒。收益是脚本不再对会话生命周期做任何假设,也不用去记框架的各种闲置参数。


## 四、顺带定下的三条纪律


第一,长睡眠不放在持有浏览器会话的进程里。需要延迟,就拆成两次独立调用,中间让会话正常退出。


第二,任何"提交后可能延迟到账"的动作,即时结果和最终结果要分开记。即时结果证明文件已经落地,最终结果证明结算发生,两者缺一都会导致误判。曾经把八分钟后才出现的记录当成失败,差点重复提交。


第三,读状态一律以明细数据为准,不以上一屏的缓存数值为准。页面顶部的总分刷新常常滞后一行,用弹窗里的逐条记录做加减,误差最小。


## 五、小结


自动化里最容易被忽视的依赖,是"执行环境会一直在"。会话、标签、上下文编号都有寿命,而延迟结算、审核、异步队列这些业务行为又天然跨越这个寿命。把状态外置成检查点,让每次执行都从文件重新起步,比在会话里硬等可靠得多。写脚本时多问一句:这段等待期间,我依赖的东西还活着吗?


【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。