本頁內容涵蓋遠端快取、設定伺服器來代管快取,以及如何透過遠端快取執行建構作業。
開發人員團隊和/或持續整合 (CI) 系統會使用遠端快取來共用建構輸出內容。假使建構作業可重現,則系統可以放心地將一部機器的輸出內容重複用於其他機器,這可大幅加快建構作業的速度。
總覽
Bazel 將建構作業拆分成獨立的步驟,這些步驟稱為動作。每個動作都包含輸入內容、輸出名稱、指令列和環境變數。系統會明確為每個動作宣告必要的輸入和預期的輸出內容。
您可以將伺服器設為建構輸出內容的遠端快取,這些輸出內容就是這些動作的輸出內容。這些輸出包含輸出檔案名稱清單及其內容的雜湊。您可以透過遠端快取重複使用其他使用者建構作業的建構輸出內容,不必在本機建構每個新的輸出內容。
遠端快取的使用方式如下:
- 將伺服器設為快取的後端
- 設定 Bazel 建構作業以使用遠端快取
- 使用 Bazel 0.10.0 以上版本
遠端快取會儲存兩種類型的資料:
- 動作快取,也就是動作雜湊與動作結果中繼資料的對應。
- 輸出檔案的內容定址存放區 (CAS)。
請注意,遠端快取會額外儲存每個動作的 stdout 和 stderr。檢查 Bazel 的 stdout/stderr 並不是估算快取命中資料的理想信號。
建構作業如何使用遠端快取
將伺服器設為遠端快取後,您可以透過多種方式使用快取:
- 讀取及寫入遠端快取
- 讀取及/或寫入遠端快取 (特定目標除外)
- 僅從遠端快取讀取
- 完全不使用遠端快取
當您執行可讀取及寫入遠端快取的 Bazel 建構作業時,建構作業會遵循下列步驟:
- Bazel 會建立需要建構的目標圖表,然後建立必要動作清單。每個動作都有宣告的輸入和輸出檔案名稱
- Bazel 會檢查本機電腦中是否有現有的建構輸出內容,並重複使用找到的所有輸出內容。
- Bazel 會檢查現有建構輸出內容的快取。找到輸出內容之後,Bazel 就會擷取輸出內容。這是快取命中
- 針對找不到輸出內容的必要動作,Bazel 會在本機執行動作,並建立所需的建構輸出內容。
- 新的建構輸出內容會上傳至遠端快取。
設定伺服器做為快取後端
您必須設定伺服器做為快取後端。HTTP/1.1 伺服器可以將 Bazel 的資料視為不透明位元組,因此許多現有伺服器可以做為遠端快取後端。Bazel 的 HTTP 快取通訊協定是支援遠端快取的功能。
您必須負責選擇、設定及維護用來儲存快取輸出結果的後端伺服器。選擇伺服器時,請考量下列幾點:
- 網路速度。舉例來說,如果您的團隊在同一間辦公室,您可能需要執行自己的本機伺服器。
- 安全性遠端快取將擁有二進位檔,因此必須能夠安全使用。
- 管理便利。舉例來說,Google Cloud Storage 是全代管服務。
有許多後端可用於遠端快取。部分選項包括:
nginx
nginx 是開放原始碼網路伺服器。[WebDAV 模組] 可讓您將其做為 Bazel 的遠端快取。在 Debian 和 Ubuntu 上,您可以安裝 nginx-extras
套件。macOS 上的 nginx 可透過 Homebrew 使用:
brew tap denji/nginx
brew install nginx-full --with-webdav
以下是 nginx 的設定範例。請注意,您必須將 /path/to/cache/dir
變更為 nginx 具有寫入和讀取權限的有效目錄。如果輸出檔案較大,則可能需要將 client_max_body_size
選項變更為較大值。伺服器需要其他設定,例如驗證。
nginx.conf
中的 server
區段設定範例:
location /cache/ {
# The path to the directory where nginx should store the cache contents.
root /path/to/cache/dir;
# Allow PUT
dav_methods PUT;
# Allow nginx to create the /ac and /cas subdirectories.
create_full_put_path on;
# The maximum size of a single file.
client_max_body_size 1G;
allow all;
}
Bazel-remote
bazel-remote 是一種開放原始碼遠端建構快取,可用於基礎架構。自 2018 年初起,就有許多幾間公司成功在實際工作環境中使用。請注意,Bazel 專案不會為 bazel-remote 提供技術支援。
這個快取會將內容儲存在磁碟中,並提供垃圾收集來強制執行上限,並清除未使用的構件。快取會以 [docker 映像檔] 的形式提供,您可以在 GitHub 找到相關程式碼。系統支援 REST 和 gRPC 遠端快取 API。
如需使用說明,請參閱 GitHub 頁面。
Google Cloud Storage
[Google Cloud Storage] 是全代管的物件儲存庫,提供的 HTTP API 與 Bazel 的遠端快取通訊協定相容。您必須擁有已啟用計費功能的 Google Cloud 帳戶。
如要使用 Cloud Storage 做為快取,請按照下列指示操作:
建立儲存空間值區。 網路頻寬對遠端快取很重要,因此請務必選取離您的最近的值區位置。
為 Bazel 建立服務帳戶,以便進行 Cloud Storage 驗證。請參閱「建立服務帳戶」一節。
產生密鑰 JSON 金鑰,然後傳送至 Bazel 進行驗證。請妥善儲存金鑰,因為凡是擁有金鑰的使用者,都能在您的 GCS 值區讀取及寫入任意資料。
將以下標記新增至 Bazel 指令,以連線至 Cloud Storage:
- 使用旗標將下列網址傳送至 Bazel:
--remote_cache=https://storage.googleapis.com/bucket-name
,其中bucket-name
是儲存空間值區的名稱。 - 透過以下標記傳遞驗證金鑰:
--google_credentials=/path/to/your/secret-key.json
或--google_default_credentials
,以使用應用程式驗證。
- 使用旗標將下列網址傳送至 Bazel:
您可以將 Cloud Storage 設定為自動刪除舊檔案。詳情請參閱管理物件生命週期。
其他伺服器
您可以將任何支援 PUT 和 GET 的 HTTP/1.1 伺服器設為快取的後端。使用者表示,快取後端 (例如 Hazelcast、Apache httpd 和 AWS S3) 達到成功。
驗證
自 0.11.0 版起,Bazel 已新增對「HTTP 基本驗證」的支援。您可以透過遠端快取網址將使用者名稱和密碼傳送至 Bazel。語法為 https://username:password@hostname.com:port/path
。請注意,HTTP 基本驗證會透過網路以明文傳輸使用者名稱和密碼,因此務必務必將其與 HTTPS 一起使用。
HTTP 快取通訊協定
Bazel 支援透過 HTTP/1.1 進行遠端快取。通訊協定的概念很簡單:二進位檔資料 (BLOB) 是透過 PUT 要求上傳,並透過 GET 要求下載。動作結果中繼資料會儲存在路徑 /ac/
下,輸出檔案則儲存在路徑 /cas/
底下。
舉例來說,假設遠端快取是在 http://localhost:8080/cache
下執行。針對含有 SHA256 雜湊 01ba4719...
的動作,Bazel 要求下載動作結果中繼資料會如下所示:
GET /cache/ac/01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b HTTP/1.1
Host: localhost:8080
Accept: */*
Connection: Keep-Alive
將含有 SHA256 雜湊 15e2b0d3...
的輸出檔案上傳到 CAS 的 Bazel 要求應如下所示:
PUT /cache/cas/15e2b0d3c33891ebb0f1ef609ec419420c20e320ce94c65fbc8c3312448eb225 HTTP/1.1
Host: localhost:8080
Accept: */*
Content-Length: 9
Connection: Keep-Alive
0x310x320x330x340x350x360x370x380x39
使用遠端快取執行 Bazel
將伺服器設為遠端快取後,如要使用遠端快取,您需要在 Bazel 指令中新增標記。請參閱下方的設定清單及相關旗標。
您可能也會需要設定所選伺服器專屬的驗證作業。
建議您將這些標記新增至 .bazelrc
檔案,這樣就不需在每次執行 Bazel 時指定這些標記。視專案和團隊的動態而定,您可以在符合下列條件的 .bazelrc
檔案中新增標記:
- 本機電腦
- 與團隊共用專案的工作區
- 在持續整合系統上
讀取及寫入遠端快取
請瞭解有權寫入遠端快取的人員。您可能只想讓 CI 系統寫入遠端快取。
使用以下旗標讀取遠端快取並寫入資料:
build --remote_cache=http://your.host:port
除了 HTTP
以外,系統也支援下列通訊協定:HTTPS
、grpc
、grpcs
。
除了上述標記以外,也請使用以下標記來僅讀取遠端快取:
build --remote_upload_local_results=false
使用遠端快取排除特定目標
如要利用遠端快取排除特定目標,請使用 no-remote-cache
標記目標。例如:
java_library(
name = "target",
tags = ["no-remote-cache"],
)
從遠端快取中刪除內容
從遠端快取中刪除內容是管理伺服器的一環。 從遠端快取中刪除內容的方式取決於您設為快取的伺服器。刪除輸出時,您可以刪除整個快取或刪除舊輸出內容。
快取的輸出內容會儲存為一組名稱和雜湊。刪除內容時,您無法區分哪些輸出屬於特定建構項目。
您可能會想刪除快取內容,以便:
- 在快取中毒後建立乾淨的快取
- 刪除舊的輸出內容,藉此減少使用的儲存空間
Unix 通訊端
遠端 HTTP 快取支援透過 Unix 網域通訊端連線。行為與 curl 的 --unix-socket
旗標類似。使用下列指令設定 Unix 網域通訊端:
build --remote_cache=http://your.host:port
build --remote_proxy=unix:/path/to/socket
Windows 不支援這項功能。
磁碟快取
Bazel 可以將檔案系統中的目錄做為遠端快取使用。您在切換分支版本及/或處理同一專案的多個工作區 (例如多個結帳) 時,可以用這個方式分享建構構件。由於 Bazel 不會垃圾收集目錄,因此建議您定期自動清理這個目錄。啟用磁碟快取,如下所示:
build --disk_cache=path/to/build/cache
您可以使用 ~
別名,將使用者專屬路徑傳送至 --disk_cache
旗標 (Bazel 會取代目前使用者的主目錄)。透過在 .bazelrc
檔案中檢查專案的所有開發人員啟用磁碟快取時,這項功能非常實用。
已知問題
在建構期間修改輸入檔案
在建構期間修改輸入檔案時,Bazel 可能會將無效結果上傳到遠端快取。您可以使用 --experimental_guard_against_concurrent_changes
旗標啟用變更偵測功能。沒有任何已知問題,我們會在日後的版本中預設啟用這項功能。請參閱 [問題 #3360] 瞭解最新資訊。一般來說,請避免在建構期間修改來源檔案。
環境變數落入動作
動作定義包含環境變數。跨裝置共用遠端快取命中時,可能會發生問題。舉例來說,採用不同 $PATH
變數的環境不會共用快取命中資料。動作定義只會包含透過 --action_env
明確加入許可清單的環境變數。用來安裝 /etc/bazel.bazelrc
的 Bazel Debian/Ubuntu 套件包含包含 $PATH
的環境變數許可清單。如果快取命中的次數不如預期,請檢查環境是否沒有舊的 /etc/bazel.bazelrc
檔案。
Bazel 不會追蹤工作區以外的工具
Bazel 目前不會追蹤工作區以外的工具。舉例來說,如果動作使用 /usr/bin/
的編譯器,就會造成問題。接著,兩位安裝不同編譯器的使用者會錯誤共用快取命中,因為輸出內容不同,但具有相同的動作雜湊。請參閱問題 #4558 以取得最新資訊。
在 Docker 容器中執行建構作業時,記憶體內的增加狀態會遺失 Bazel 即使在單一 Docker 容器中執行建構作業也會使用伺服器/用戶端架構。在伺服器端,Bazel 會維持記憶體內狀態,進而加快建構速度。在 CI 等 Docker 容器中執行建構作業時,記憶體內狀態會遺失,而且 Bazel 必須在使用遠端快取前重新建構。
外部連結
透過遠端快取加快 Bazel 建構速度:基準:Nicoò Valigi 撰寫了一篇網誌文章,當中包含他利用 Bazel 進行遠端快取的基準測試。