本頁將說明遠端快取、設定快取主機伺服器,以及使用遠端快取執行建構作業。
開發人員團隊和/或持續整合 (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 上,您可以透過 Homebrew 安裝 nginx:
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] 是全代管物件儲存庫,提供與 Bazel 遠端快取通訊協定相容的 HTTP API。您必須擁有已啟用帳單功能的 Google Cloud 帳戶。
如要將 Cloud Storage 做為快取:
建立儲存空間值區。請務必選取最接近您所在位置的值區位置,因為網路頻寬對於遠端快取十分重要。
建立服務帳戶,讓 Bazel 驗證 Cloud Storage。請參閱「建立服務帳戶」。
產生 JSON 密鑰,然後將其傳遞給 Bazel 進行驗證。請妥善保存金鑰,因為任何擁有金鑰的使用者都能讀取及寫入任意資料至/自 GCS 值區。
將下列標記新增至 Bazel 指令,即可連線至 Cloud Storage:
- 使用標記
--remote_cache=https://storage.googleapis.com/bucket-name
將下列網址傳遞至 Bazel,其中bucket-name
是儲存空間值區的名稱。 - 使用標記
--google_credentials=/path/to/your/secret-key.json
或--google_default_credentials
傳遞驗證金鑰,以便使用應用程式驗證。
- 使用標記
您可以設定 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
要求 Bazel 將含有 SHA256 雜湊 15e2b0d3...
的輸出檔案上傳至 CAS 的內容如下:
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 網域 Socket:
build --remote_cache=http://your.host:port
build --remote_cache_proxy=unix:/path/to/socket
Windows 不支援這項功能。
磁碟快取
Bazel 可以使用檔案系統中的目錄做為遠端快取。在切換分支版本和/或處理同一專案的多個工作區 (例如多個檢出作業) 時,這項功能可用於共用建構構件。如要啟用磁碟快取,請按照下列步驟操作:
build --disk_cache=path/to/build/cache
您可以使用 ~
別名,將使用者專屬路徑傳遞至 --disk_cache
旗標 (Bazel 會替換目前使用者的主目錄)。在 .bazelrc
檔案中勾選專案後,您可以為專案的所有開發人員啟用磁碟快取功能。
垃圾收集
從 Bazel 7.4 開始,您可以使用 --experimental_disk_cache_gc_max_size
和 --experimental_disk_cache_gc_max_age
為磁碟快取或個別快取項目的存放期限設定上限。Bazel 會在建構作業之間閒置時自動回收磁碟快取;您可以使用 --experimental_disk_cache_gc_idle_delay
設定閒置計時器 (預設為 5 分鐘)。
我們也提供工具,可視需要執行垃圾收集,做為自動垃圾收集的替代方案。
已知問題
在建構期間修改輸入檔案
如果在建構期間修改輸入檔案,Bazel 可能會將無效的結果上傳至遠端快取。您可以使用 --experimental_guard_against_concurrent_changes
標記啟用變更偵測功能。這項功能沒有任何已知問題,且日後推出的版本將預設啟用。請參閱 [issue #3360] 瞭解最新消息。一般來說,請避免在建構期間修改來源檔案。
環境變數外洩至動作
動作定義包含環境變數。這可能會導致在不同機器之間共用遠端快取命中資料的問題。舉例來說,如果環境中的 $PATH
變數不同,就不會共用快取命中。只有透過 --action_env
明確加入許可清單的環境變數,才會納入動作定義。Bazel 的 Debian/Ubuntu 套件,用於安裝 /etc/bazel.bazelrc
,並使用包含 $PATH
的環境變數白名單。如果快取命中次數低於預期,請確認環境中沒有舊的 /etc/bazel.bazelrc
檔案。
Bazel 不會追蹤工作區以外的工具
Bazel 目前不會追蹤工作區以外的工具。舉例來說,如果動作使用 /usr/bin/
的編譯器,就可能發生這個問題。接著,兩位安裝不同編譯器的使用者會因為輸出內容不同,但動作雜湊相同,而誤將快取命中結果共用。如需最新資訊,請參閱問題 #4558。
在 Docker 容器中執行建構作業時,記憶體中的增量狀態會遺失:即使在單一 Docker 容器中執行,Bazel 也會使用伺服器/用戶端架構。在伺服器端,Bazel 會維護記憶體內狀態,加快建構作業。在 Docker 容器 (例如 CI) 中執行建構作業時,記憶體內的狀態會遺失,因此 Bazel 必須先重建記憶體內的狀態,才能使用遠端快取。