Grid 架构

Grid 被设计为一组组件,这些组件都在维护 Grid 中发挥作用。它看起来可能相当复杂,但希望本文档能够帮助消除任何困惑。

关键组件

Grid 的主要组件是

事件总线
用于在其他组件之间异步发送可能接收的消息。
新会话队列
维护尚未由分配器分配给节点的传入会话列表。
分配器
负责维护 Grid 中可以运行会话的可用位置的模型(称为“插槽”),并接受任何传入的新会话请求并将它们分配给一个插槽。
节点
运行一个WebDriver 会话。每个会话都分配到一个插槽,每个节点都有一个或多个插槽。
会话映射
维护会话 ID与运行会话的节点地址之间的映射。
路由器
充当 Grid 的前端。这是 Grid 中唯一可能暴露给更广泛的 Web 的部分(尽管我们强烈建议不要这样做)。它将传入的请求路由到新会话队列或运行会话的节点。

在讨论 Grid 时,还有一些其他有用的概念需要牢记

  • 一个 插槽 是可以运行会话的地方。
  • 每个插槽都有一个 刻板印象。这是新会话会话请求必须匹配的最小功能集,然后分配器才会将该请求发送到拥有该插槽的节点。
  • Grid 模型 是分配器如何跟踪 Grid 的状态。顾名思义,有时这可能会与现实不同步(可能是因为分配器才刚刚启动)。它优先于查询每个节点,以便分配器可以快速将一个插槽分配给新会话请求。

同步和异步调用

Grid 中使用了两种主要的通信机制

  1. 通过 HTTP 请求的同步 “REST-ish” JSON。
  2. 发送到事件总线的异步事件。

我们如何选择使用哪种通信机制?毕竟,我们可以以基于事件的方式对整个 Grid 进行建模,并且它也可以正常工作。

答案是,如果执行的操作是同步的(例如,大多数 WebDriver 调用),或者如果丢失响应会产生问题,则 Grid 使用同步调用。相反,如果我们想向任何感兴趣的人广播信息,或者如果丢失响应无关紧要,那么我们更喜欢使用事件总线。

一个有趣的事情是,异步调用比同步调用与它们的侦听器更加解耦。

组件之间的启动顺序和依赖关系

虽然 Grid 设计为允许组件以任何顺序启动,但从概念上讲,组件的启动顺序是

  1. 事件总线和会话映射首先启动。这些没有其他依赖项,甚至彼此之间都没有,因此可以安全地并行启动。
  2. 接下来启动会话队列。
  3. 现在可以启动分配器了。这将定期连接到会话队列并轮询作业,尽管此轮询可能由事件(将新会话添加到队列中)或定期启动。
  4. 可以启动路由器。新会话请求将被定向到会话队列,分配器将尝试找到一个插槽来运行会话。
  5. 我们现在可以启动一个节点了。有关如何将节点注册到 Grid 的详细信息,请参见下文。注册完成后,Grid 即可提供流量。

你可以这样描绘组件之间的依赖关系,其中 “✅” 表示组件之间存在同步依赖关系。

事件总线分配器节点路由器会话映射会话队列
事件总线X
分配器X
节点X
路由器X
会话映射X
会话队列X

节点注册

将新节点注册到 Grid 的过程是轻量级的。

  1. 当节点启动时,它应该定期发出“心跳”事件。此心跳包含节点状态
  2. 分配器侦听心跳事件。当它看到一个时,它会尝试 GET 节点的 /status 端点。正是通过此信息设置 Grid。

分配器将使用相同的 /status 端点定期检查节点,但即使在启动后,节点也应继续发送心跳事件,以便没有 Grid 状态持久存储的分配器可以重新启动,并且(最终)将是最新的和正确的。

节点状态对象

节点状态是一个 JSON blob,包含以下字段

名称类型描述
可用性字符串一个字符串,可以是 updrainingdown 之一。重要的是 draining,它表示不应将新会话发送到节点,并且一旦其上的最后一个会话关闭,节点将退出或重新启动。
externalUrl字符串Grid 中其他组件应连接到的 URI。
lastSessionCreated整数上次在此节点上创建会话的纪元时间戳。如果所有其他条件都相同,分配器将尝试将新会话发送到空闲时间最长的节点。
maxSessionCount整数尽管可以通过计算可用插槽的数量来推断会话计数,但此整数值用于确定在节点被视为“已满”之前应同时运行的最大会话数。
nodeId字符串用于标识此节点实例的 UUID。
osInfo对象一个包含 archnameversion 字段的对象。这由 Grid UI 和 GraphQL 查询使用。
slots数组一个插槽对象数组(如下所述)
version字符串节点版本(对于 Selenium,这将与 Selenium 版本号匹配)

建议在所有字段中都放置值。

插槽对象

插槽对象表示节点中的单个插槽。“插槽”是单个会话可以运行的地方。节点可能具有比其可以同时运行的更多插槽。例如,一个节点可能能够运行多达 10 个会话,但它们可以是 Chrome、Edge 或 Firefox 的任意组合;在这种情况下,该节点将指示“最大会话数”为 10,然后还说它有 10 个 Chrome 插槽、10 个 Edge 插槽和 10 个 Firefox 插槽。

名称类型描述
id字符串用于引用插槽的 UUID
lastStarted字符串上次插槽启动会话的时间,采用 ISO-8601 格式
stereotype对象此插槽将匹配的最小功能集。一个最小的示例是 {"browserName": "firefox"}
session对象会话对象(见下文)

会话对象

这表示插槽中正在运行的会话

名称类型描述
capabilities对象会话提供的实际功能。将与新会话命令的返回值匹配
startTime字符串会话的开始时间,采用 ISO-8601 格式
stereotype对象此插槽将匹配的最小功能集。一个最小的示例是 {"browserName": "firefox"}
uri字符串节点用于与会话通信的 URI
上次修改时间:2022 年 8 月 29 日: 更新 Grid 架构 (9df8227bc4c)