Edge 自动化工具自升级后扩展失联:一次 0.4.0 升级的现场排障
背景
我用一套本地浏览器自动化 CLI(下称 bsk)驱动真实 Edge 做日常网页操作。它由两部分组成:本地守护进程(daemon)和浏览器扩展,两者通过 WebSocket 通信。今天上午开机后,daemon 自动从 0.3.3 升级到 0.4.0,随后扩展就再也连不上了。这篇文章记录完整的排障过程,重点是几个容易被误判的环节。
现象:三个层次同时"看起来正常"
升级完成后,首次执行健康检查,大部分项目是绿的:
ok daemon running pid 22072 at ws://127.0.0.1:52800
ok protocol compatible daemon protocol 1.7 (app 0.4.0)
ok auto-update 0.3.3 -> 0.4.0 succeeded
FAIL extension connected 0 browsers connected
daemon 在跑、端口在监听、协议自洽,唯独扩展侧计数为 0。此时最容易得出的错误结论是"扩展坏了,重装吧"。但日志给出了另一条线索。
关键证据:日志里的 generation 变化
daemon 日志按时间顺序记录了三件事:
03:00:20 替换 daemon 启动(0.3.3 -> 0.4.0),旧进程退出
03:01:55 browser protocol minor drift; peer_protocol=1.3, daemon_protocol=1.7
03:01:55 browser connected generation=1
03:04:05 reaping unresponsive browser (no heartbeat), idle_secs=66
03:04:41 browser disconnected; newer reconnect already owns this id
03:10:29 browser connected generation=2
三个事实:
- 扩展确实连上过,只是带着协议 1.3 去连协议 1.7 的 daemon,daemon 只记了一条 WARN 就放行了;
- 断开不是因为被拒绝,而是心跳超时(66 秒无心跳被判失联);
- 扩展会自己重连,6 分钟后 generation 从 1 变成 2 又连上了。
所以真正的状态是"能连但会掉,掉了会自愈",而不是"连不上"。
为什么心跳会超时:跨版本的行为差异
扩展是商店版 0.3.3,daemon 已经升到 0.4.0。daemon 侧判定失联的存活窗口在 0.4.0 里收紧了,而 0.3.3 扩展的心跳间隔比这个窗口更长,于是每次心跳都"迟到",稳定被判失联。日志里的 idle_secs=66 就是这个窗口被撑爆的读数。
这里有个容易踩的坑:协议版本不匹配时 daemon 并不拒绝连接,只打一条 WARN。所以不会看到显式的版本错误,只会表现成间歇性掉线,很容易被误判成网络抖动。
第二个坑:会话空闲超时比想象中短
连上之后我以为可以开始干活了,结果第一次执行操作就报错:
error: the session stopped after its idle timeout
hint: run the daemon with a larger --session-idle (default 5m)
默认会话空闲超时只有 5 分钟。对于"打开网页、读一会儿、再操作"这种节奏完全不够用,而且——这一点很反直觉——这个超时是按"没有命令往来"计算的,不是按页面是否在活动计算的。视频在播、页面在动,只要我没发命令,会话照样被回收,连带把 Agent Window 和它开的所有标签页一起关掉。
解决办法是重启 daemon 时显式放大两个超时:
bsk daemon restart --session-idle 2h --daemon-idle 6h
注意这两个参数是 daemon 的启动参数,不是会话参数,写在 session start 上无效。
第三个坑:0x0 视口,以及它为什么"看起来像播放器坏了"
重开会话后,我打开一个视频课程页准备让它自动播放。播放器完全没反应,video 元素的 readyState 一直是 0,buffered 为空,但 networkState 是 2(正在加载)。看起来像是 CDN 挂了或者编码不被支持。
实际原因是这个:
{ "innerWidth": 0, "innerHeight": 0, "bodyWidth": 0 }
视口宽高是 0。页面布局宽度为 0,播放器容器拿不到尺寸,自然不会去请求视频。证据链很直接——同一个页面上,.video_main 容器的 offsetWidth 也是 0,而 offsetHeight 有 230,说明不是元素被隐藏,是整个渲染视口没有尺寸。
触发条件是会话以"后台不抢焦点"方式启动:session start --no-focus。Agent Window 不会真正显示出来,Chromium 就不给它分配视口。用 --focus 启动后立刻正常:
{ "innerWidth": 1178, "innerHeight": 721 }
{ "hasVideo": true, "readyState": 4, "duration": 963 }
这条经验的推广价值在于:播放器"不加载"、懒加载图片不出、IntersectionObserver 不触发,都先查视口尺寸再查网络。视口为 0 时,readyState 的表现和网络故障几乎一模一样。
验证方法:别只看"连接数=1"
只看 browsers connected 的瞬时值很容易被骗——它 1 分钟前还可能是 1。更可靠的做法是持续采样并观察代际变化:
for i in $(seq 1 12); do
sleep 10
n=$(bsk status 2>&1 | grep "browsers connected" | awk '{print $3}')
echo "t=$((i*10))s browsers=$n"
[ "$n" != "0" ] && break
done
配合 daemon 日志的 generation 字段,就能区分三种状态:连不上(计数恒 0 且无 connected 记录)、能连但会掉(connected/disconnected 交替、generation 增长)、稳定(计数持续为 1 且无 reaping 记录)。
小结
- 自动升级会带来版本漂移:CLI/daemon 升了,浏览器扩展未必跟着升。日志里的
protocol drift是唯一的提示,不报错只报警。 - 失联判据是心跳超时而非连接被拒。看到
reaping unresponsive应该往心跳间隔方向查,而不是怀疑扩展损坏。 - 会话空闲超时默认 5 分钟,且按命令往来计时,与页面活动无关;长任务要提前用
--session-idle放大。 - 视口 0×0 会让整个页面"看起来加载失败",检查
innerWidth比翻网络面板快得多。 - 完成判据要选可持续观测的指标:连接代际、进程启动时间、行为探针;任何单次读数都可能踩在抖动的瞬间上。
- 点赞
- 收藏
- 关注作者
评论(0)