網格架構
Grid 被設計為一組組件,這些組件都在維護 Grid 中發揮作用。它可能看起來相當複雜,但希望本文檔可以幫助消除任何混淆。
主要組件
Grid 的主要組件包括
- 事件總線
- 用於在其他組件之間非同步傳送可能被接收的消息。
- 新工作階段佇列
- 維護尚未由分配器指派給節點的傳入工作階段列表。
- 分配器
- 負責維護 Grid 中可用位置的模型,工作階段可以在其中運行(稱為「插槽」),並接收任何傳入的 新工作階段 請求,並將它們指派給一個插槽。
- 節點
- 運行 WebDriver 工作階段。每個工作階段都指派給一個插槽,並且每個節點都有一個或多個插槽。
- 工作階段地圖
- 維護 工作階段 ID 與運行工作階段的節點位址之間的映射。
- 路由器
- 充當 Grid 的前端。這是 Grid 中可能暴露於更廣泛網路的唯一部分(儘管我們強烈建議不要這樣做)。這會將傳入的請求路由到新工作階段佇列或運行工作階段的節點。
在討論 Grid 時,還有一些其他有用的概念需要記住
- 插槽是工作階段可以運行的位置。
- 每個插槽都有一個原型。這是 新工作階段 工作階段請求必須匹配的最小功能集,分配器才會將該請求發送到擁有該插槽的節點。
- Grid 模型是分配器如何追蹤 Grid 的狀態。顧名思義,這有時可能會與現實脫節(可能是因為分配器才剛啟動)。它優先於查詢每個節點,以便分配器可以快速地將插槽指派給新的工作階段請求。
同步和非同步呼叫
Grid 內使用了兩種主要的通訊機制
- 同步的「類 REST 風格」JSON over HTTP 請求。
- 傳送到事件總線的非同步事件。
我們如何選擇使用哪種通訊機制?畢竟,我們可以以基於事件的方式對整個 Grid 建模,它也能正常運作。
答案是,如果正在執行的操作是同步的(例如,大多數 WebDriver 呼叫),或者如果遺失回應會造成問題,則 Grid 會使用同步呼叫。相反,如果我們想要將資訊廣播給任何感興趣的人,或者如果遺失回應並不重要,那麼我們更喜歡使用事件總線。
一個有趣的注意事項是,非同步呼叫比同步呼叫更與其監聽器解耦。
啟動順序和組件之間的依賴關係
儘管 Grid 被設計為允許組件以任何順序啟動,但概念上組件啟動的順序是
- 事件總線和工作階段地圖首先啟動。這些沒有其他依賴項,甚至彼此之間也沒有,因此可以安全地並行啟動。
- 工作階段佇列接下來啟動。
- 現在可以啟動分配器了。這將定期連接到工作階段佇列並輪詢作業,儘管此輪詢可能由事件(已將新工作階段新增到佇列中)或定期間隔啟動。
- 可以啟動路由器。新的工作階段請求將被定向到工作階段佇列,並且分配器將嘗試尋找一個插槽來運行工作階段。
- 我們現在可以啟動節點了。有關節點如何在 Grid 中註冊的詳細資訊,請參閱下文。註冊完成後,Grid 即可準備好服務流量。
您可以這樣描繪組件之間的依賴關係,其中「✅」表示組件之間存在同步依賴關係。
事件總線 | 分配器 | 節點 | 路由器 | 工作階段地圖 | 工作階段佇列 | |
---|---|---|---|---|---|---|
事件總線 | X | |||||
分配器 | ✅ | X | ✅ | ✅ | ||
節點 | ✅ | X | ||||
路由器 | ✅ | X | ✅ | |||
工作階段地圖 | X | |||||
工作階段佇列 | ✅ | X |
節點註冊
將新節點註冊到 Grid 的過程很輕量。
- 當節點啟動時,它應該定期發出「心跳」事件。此心跳包含 節點狀態。
- 分配器監聽心跳事件。當它看到一個時,它會嘗試
GET
節點的/status
端點。Grid 就是從此資訊設定的。
分配器將使用相同的 /status
端點定期檢查節點,但節點應在啟動後繼續發送心跳事件,以便沒有 Grid 狀態持久儲存的分配器可以重新啟動,並且(最終)將是最新的和正確的。
節點狀態物件
節點狀態是一個 JSON blob,具有以下欄位
名稱 | 類型 | 描述 |
---|---|---|
可用性 | 字串 | 一個字串,它是 up 、draining 或 down 之一。重要的是 draining ,它表示不應將新的工作階段發送到節點,並且一旦節點上的最後一個工作階段關閉,節點將退出或重新啟動。 |
externalUrl | 字串 | Grid 中的其他組件應連接到的 URI。 |
lastSessionCreated | 整數 | 上次在此節點上建立工作階段的 epoch 時間戳記。如果所有其他條件都相同,分配器將嘗試將新工作階段發送到閒置時間最長的節點。 |
maxSessionCount | 整數 | 儘管可以通過計算可用插槽的數量來推斷工作階段計數,但此整數值用於確定在節點被視為「已滿」之前應同時在其上運行的最大工作階段數。 |
nodeId | 字串 | 用於識別此節點實例的 UUID。 |
osInfo | 物件 | 具有 arch 、name 和 version 欄位的物件。這由 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 |