本頁說明多重工作站、如何編寫與多重相容的規則,以及特定限制的解決方法。
多重工作站可讓 Bazel 透過單一 worker 程序處理多個要求。對於多執行緒工作者,Bazel 可以使用較少的資源來達到相同或更佳的效能。舉例來說,Bazel 可讓四個多重化工作站與同一個工作站程序進行通訊,而非每個工作站都有一個工作站程序,這樣一來,系統就能並行處理要求。對於 Java 和 Scala 等語言,這可節省 JVM 暖機時間和 JIT 編譯時間,而且通常可在同類型工作站之間使用一個共用快取。
總覽
Bazel 伺服器和 worker 程序之間有兩個層級。對於可並行執行程序的特定助憶法,Bazel 會從工作站集區取得 WorkerProxy
。WorkerProxy
會依序將要求和 request_id
轉送至 worker 處理程序,worker 處理程序會處理要求,並將回應傳送至 WorkerMultiplexer
。WorkerMultiplexer
收到回應時,會剖析 request_id
,然後將回應轉寄回正確的 WorkerProxy
。與非多工處理 worker 一樣,所有通訊都會透過標準輸入/輸出完成,但工具無法只使用 stderr
來顯示使用者可見的輸出內容 (請見下文)。
每個 worker 都有一個鍵。Bazel 會使用鍵的雜湊碼 (由環境變數、執行根目錄和助憶符號組成) 來決定要使用的 WorkerMultiplexer
。如果 WorkerProxy
具有相同的雜湊碼,就會與相同的 WorkerMultiplexer
通訊。因此,假設在單一 Bazel 叫用中,環境變數和執行根目錄相同,則每個專屬助憶碼只能有一個 WorkerMultiplexer
和一個 worker 程序。包括一般工作站和 WorkerProxy
在內的工作站總數仍受 --worker_max_instances
限制。
編寫多重相容規則
規則的工作站程序應為多執行緒,以便充分利用多工工作站。Protobuf 允許規則集解析單一要求,即使串流中可能有許多要求堆積。只要 worker 程序剖析來自串流的請求,就應在新執行緒中處理該要求。由於不同的執行緒可能會同時完成並寫入串流,因此工作程序需要確保回應是按順序寫入 (訊息不會重疊)。回應必須包含所處理要求的 request_id
。
處理多重輸出
多重工作站比單一工作站更需要小心處理輸出內容。所有傳送至 stderr
的內容都會進入單一記錄檔案,並由所有相同類型的 WorkerProxy
共用,並在並行要求之間隨機交錯。雖然將 stdout
重新導向至 stderr
是個好主意,但請勿將該輸出內容收集至 WorkResponse
的 output
欄位,因為這可能會向使用者顯示經過竄改的輸出內容。如果您的工具只將以使用者為導向的輸出內容傳送至 stdout
或 stderr
,您必須先變更該行為,才能啟用多重工作站。
啟用多重工作站
根據預設,系統不會啟用多重工作站。規則集可在動作的 execution_requirements
中使用 supports-multiplex-workers
標記來啟用多工工作站 (就像 supports-workers
標記可啟用一般工作站一樣)。與使用一般工作站的情況相同,您需要在規則集層級 (例如 --strategy=[some_mnemonic]=worker
) 或一般策略層級 (例如 --dynamic_local_strategy=worker,standalone
) 指定 worker 策略。如果同時設定這兩個層級,supports-multiplex-workers
會優先於 supports-workers
。您可以傳遞 --noexperimental_worker_multiplex
,在全球範圍內關閉多工工作站。
建議您盡可能使用多重工作者規則集,以減少記憶體壓力並提升效能。不過,除非實作多重沙箱功能,否則多重工作站目前不相容於動態執行。如果嘗試以動態執行方式執行非沙箱化的多工工作,系統會改為靜默使用沙箱化的單工工作。
多重廣告沙箱機制
您可以在 worker 實作中加入明確的支援,藉此將多重工作站置入沙箱。雖然單一工作站的沙箱作業可以透過在各自的沙箱中執行每個工作站程序來完成,但多重工作站會在多個並行要求之間共用程序工作目錄。為了讓多重工作站進行沙箱處理,工作站必須支援從每個要求中指定的子目錄讀取及寫入資料,而非直接在其工作目錄中執行。
為了支援多重沙箱功能,工作站必須使用 WorkRequest
中的 sandbox_dir
欄位,並將其用作所有檔案讀取和寫入作業的字首。雖然 arguments
和 inputs
欄位與未隔離的要求保持不變,但實際輸入內容會與 sandbox_dir
相關。工作站必須轉譯 arguments
和 inputs
中的檔案路徑,才能讀取這個修改過的路徑,並且必須相對於 sandbox_dir
寫入所有輸出內容。這包括 '.' 等路徑,以及在引數中指定的檔案中找到的路徑 (例如 "argfile" 引數)。
一旦 worker 支援多重沙箱功能,規則集就可以在動作的 execution_requirements
中加入 supports-multiplex-sandboxing
,宣告這項支援。如果傳遞 --experimental_worker_multiplex_sandboxing
標記,或是使用 worker 搭配動態執行,Bazel 就會使用多重沙箱。
沙箱多重工作站工作站的 worker 檔案仍以 worker 程序的工作目錄為基準。因此,如果檔案同時用於執行 worker 和做為輸入內容,則必須在 flagfile 引數和 tools
、executable
或 runfiles
中同時指定該檔案做為輸入內容。