在 Playwright 工作队列中使用路由键和配置文件租约

Playwright 的错误(例如 TimeoutError: page.click failed)往往具有误导性。

错误告诉你脚本看到了什么,但它并没有告诉你为什么脚本一开始就处于错误的位置。

我曾见过两个工作节点(worker)同时领取了同一个账号的任务。两个节点同时打开了同一个浏览器配置文件。其中一个节点正在等待一个加载缓慢的页面,而另一个节点尝试重试并更改了会话状态,从而导致了失败。

问题不在于代码,而在于队列。

大多数工作队列是为无状态任务设计的:

  • 领取任务。
  • 寻找空闲工作节点。
  • 执行任务。
  • 标记完成。

这对于截图或 API 调用是有效的,但对于浏览器自动化则会失败。

浏览器配置文件不是无状态的。它属于一个特定的账号、一个代理和一个会话状态。最快的节点并不总是最合适的节点。

为了实现安全扩展,你必须转变逻辑。

不要问: 哪个节点是空闲的?

而要问: 现在哪个账号环境是可以安全使用的?

你可以通过以下三个层面来解决这个问题:

  1. 路由键 (Routing Keys) 不要让任何节点领取任何任务。使用基于配置文件 ID 或账号 ID 的路由键。这能确保同一时间只有一个节点操作特定的配置文件。

  2. 配置文件租约 (Profile Leases) “队列领取”意味着一个节点拥有一个任务;而“配置文件租约”意味着一个节点被允许在设定时间内使用特定的浏览器配置文件。使用带有“心跳”(heartbeat)机制的租约。如果任务耗时超出预期,工作节点必须续约。

  3. 栅栏令牌 (Fencing Tokens) 失效的工作节点是危险的。如果一个节点因网络延迟丢失了租约但仍在继续运行,它可能会尝试写入数据。使用栅栏令牌。存储层应当拒绝任何来自旧令牌的写入请求。

你还必须添加一个就绪门控(readiness gate)。在启动 Playwright 之前,请检查以下内容:

  • 账号是否已暂停?
  • 配置文件是否需要人工审核?
  • 代理区域是否符合任务要求?

被阻塞的任务并不总是失败的任务。它通常只是一个正在等待合适上下文的任务。

不要再构建只追求速度的队列了。要构建优先考虑账号状态的队列。

Source: https://dev.to/web4browser/using-routing-keys-and-profile-leases-in-playwright-worker-queues-a53