रिमोट कैशिंग

समस्या की शिकायत करें सोर्स देखें Nightly · 8.4 · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

इस पेज पर, रिमोट कैश मेमोरी, कैश मेमोरी को होस्ट करने के लिए सर्वर सेट अप करने, और रिमोट कैश मेमोरी का इस्तेमाल करके बिल्ड चलाने के बारे में बताया गया है.

रिमोट कैश मेमोरी का इस्तेमाल, डेवलपर की टीम और/या लगातार इंटिग्रेशन (सीआई) सिस्टम करता है, ताकि बिल्ड आउटपुट शेयर किए जा सकें. अगर आपका बिल्ड फिर से बनाया जा सकता है, तो एक मशीन से मिले आउटपुट को दूसरी मशीन पर सुरक्षित तरीके से फिर से इस्तेमाल किया जा सकता है. इससे बिल्ड को काफ़ी तेज़ी से बनाया जा सकता है.

खास जानकारी

Bazel, बिल्ड को अलग-अलग चरणों में बांटता है. इन्हें ऐक्शन कहा जाता है. हर ऐक्शन में इनपुट, आउटपुट के नाम, कमांड लाइन, और एनवायरमेंट वैरिएबल होते हैं. हर कार्रवाई के लिए, ज़रूरी इनपुट और अनुमानित आउटपुट साफ़ तौर पर बताए जाते हैं.

बिल्ड आउटपुट के लिए, किसी सर्वर को रिमोट कैश के तौर पर सेट अप किया जा सकता है. ये ऐक्शन आउटपुट होते हैं. इन आउटपुट में, आउटपुट फ़ाइलों के नामों की सूची और उनके कॉन्टेंट के हैश शामिल होते हैं. रिमोट कैश की मदद से, हर नए आउटपुट को स्थानीय तौर पर बनाने के बजाय, किसी दूसरे उपयोगकर्ता की बिल्ड से मिले आउटपुट का फिर से इस्तेमाल किया जा सकता है.

रिमोट कैशिंग का इस्तेमाल करने के लिए:

  • किसी सर्वर को कैश मेमोरी के बैकएंड के तौर पर सेट अप करना
  • रिमोट कैश का इस्तेमाल करने के लिए, Bazel बिल्ड को कॉन्फ़िगर करना
  • Bazel का 0.10.0 या इसके बाद का वर्शन इस्तेमाल करें

रिमोट कैश मेमोरी में दो तरह का डेटा सेव होता है:

  • ऐक्शन कैश मेमोरी, जो ऐक्शन हैश से ऐक्शन के नतीजे के मेटाडेटा का मैप होती है.
  • आउटपुट फ़ाइलों का कॉन्टेंट-ऐड्रेसबल स्टोर (सीएएस).

ध्यान दें कि रिमोट कैश, हर कार्रवाई के लिए stdout और stderr को भी सेव करता है. इसलिए, Bazel के stdout/stderr की जांच करना, कैश हिट का अनुमान लगाने के लिए अच्छा सिग्नल नहीं है.

कोई बिल्ड, रिमोट कैश मेमोरी का इस्तेमाल कैसे करता है

किसी सर्वर को रिमोट कैश मेमोरी के तौर पर सेट अप करने के बाद, कैश मेमोरी का इस्तेमाल कई तरीकों से किया जा सकता है:

  • रिमोट कैश को पढ़ने और उसमें बदलाव करने की अनुमति दें
  • कुछ टारगेट को छोड़कर, रिमोट कैश को पढ़ने और/या लिखने की अनुमति
  • सिर्फ़ रिमोट कैश मेमोरी से डेटा पढ़ना
  • रिमोट कैश मेमोरी का इस्तेमाल न करें

जब रिमोट कैश से डेटा पढ़ने और उसमें डेटा लिखने की सुविधा देने वाला Bazel बिल्ड चलाया जाता है, तो बिल्ड यह तरीका अपनाता है:

  1. Bazel, उन टारगेट का ग्राफ़ बनाता है जिन्हें बनाने की ज़रूरत होती है. इसके बाद, ज़रूरी कार्रवाइयों की सूची बनाता है. इनमें से हर ऐक्शन के लिए, इनपुट और आउटपुट फ़ाइल के नाम तय किए गए हैं.
  2. Bazel, आपकी लोकल मशीन पर मौजूद बिल्ड आउटपुट की जांच करता है. साथ ही, उसे जो भी आउटपुट मिलते हैं उनका फिर से इस्तेमाल करता है.
  3. Bazel, मौजूदा बिल्ड आउटपुट के लिए कैश मेमोरी की जांच करता है. अगर आउटपुट मिल जाता है, तो Bazel उसे वापस ले लेता है. यह कैश मेमोरी हिट है.
  4. जिन ज़रूरी कार्रवाइयों के आउटपुट नहीं मिले हैं उनके लिए, Bazel कार्रवाइयों को स्थानीय तौर पर लागू करता है और ज़रूरी बिल्ड आउटपुट बनाता है.
  5. नई बिल्ड आउटपुट को रिमोट कैश मेमोरी में अपलोड किया जाता है.

सर्वर को कैश मेमोरी के बैकएंड के तौर पर सेट अप करना

आपको एक सर्वर सेट अप करना होगा, ताकि वह कैश मेमोरी के बैकएंड के तौर पर काम कर सके. एचटीटीपी/1.1 सर्वर, Bazel के डेटा को ओपेक बाइट के तौर पर प्रोसेस कर सकता है. इसलिए, कई मौजूदा सर्वर का इस्तेमाल रिमोट कैशिंग बैकएंड के तौर पर किया जा सकता है. Bazel का एचटीटीपी कैश मेमोरी प्रोटोकॉल, रिमोट कैश मेमोरी की सुविधा के साथ काम करता है.

कैश किए गए आउटपुट को सेव करने वाले बैकएंड सर्वर को चुनने, सेट अप करने, और उसे बनाए रखने की ज़िम्मेदारी आपकी है. सर्वर चुनते समय, इन बातों का ध्यान रखें:

  • नेटवर्क की स्पीड. उदाहरण के लिए, अगर आपकी टीम एक ही ऑफ़िस में है, तो हो सकता है कि आपको अपना लोकल सर्वर चलाना हो.
  • सुरक्षा. रिमोट कैश में आपके बाइनरी होते हैं. इसलिए, इसे सुरक्षित रखना ज़रूरी है.
  • मैनेज करने में आसानी होती है. उदाहरण के लिए, Google Cloud Storage एक पूरी तरह से मैनेज की जाने वाली सेवा है.

रिमोट कैश मेमोरी के लिए, कई बैकएंड का इस्तेमाल किया जा सकता है. कुछ विकल्पों में ये शामिल हैं:

nginx

nginx एक ओपन सोर्स वेब सर्वर है. [WebDAV module] की मदद से, इसे 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 के लिए तकनीकी सहायता उपलब्ध नहीं कराता है.

यह कैश, डिस्क पर कॉन्टेंट सेव करता है. साथ ही, यह स्टोरेज की ऊपरी सीमा लागू करने और इस्तेमाल न किए गए आर्टफ़ैक्ट को हटाने के लिए, गार्बेज कलेक्शन की सुविधा भी देता है. कैश [डॉकर इमेज] के तौर पर उपलब्ध है. इसका कोड GitHub पर उपलब्ध है. REST और gRPC, दोनों रिमोट कैश एपीआई काम करते हैं.

इसे इस्तेमाल करने का तरीका जानने के लिए, GitHub पेज पर जाएं.

Google Cloud Storage

[Google Cloud Storage] एक पूरी तरह से मैनेज किया गया ऑब्जेक्ट स्टोर है. यह एक एचटीटीपी एपीआई उपलब्ध कराता है, जो Bazel के रिमोट कैशिंग प्रोटोकॉल के साथ काम करता है. इसके लिए, आपके पास बिलिंग की सुविधा वाला Google Cloud खाता होना चाहिए.

कैश के तौर पर Cloud Storage का इस्तेमाल करने के लिए:

  1. स्टोरेज बकेट बनाएं. पक्का करें कि आपने ऐसी बकेट लोकेशन चुनी हो जो आपके सबसे पास हो, क्योंकि रिमोट कैश के लिए नेटवर्क बैंडविड्थ ज़रूरी है.

  2. Bazel के लिए एक सेवा खाता बनाएं, ताकि Cloud Storage में उसकी पहचान की पुष्टि की जा सके. सेवा खाता बनाना लेख पढ़ें.

  3. एक सीक्रेट JSON कुंजी जनरेट करें. इसके बाद, पुष्टि करने के लिए इसे Bazel को पास करें. कुंजी को सुरक्षित रूप से सेव करें. ऐसा इसलिए, क्योंकि जिसके पास भी यह कुंजी होगी वह आपके GCS बकेट में मौजूद डेटा को पढ़ और उसमें बदलाव कर सकता है.

  4. 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 फ़्लैग का इस्तेमाल करके पुष्टि करने वाली कुंजी पास करें.
  5. Cloud Storage को इस तरह कॉन्फ़िगर किया जा सकता है कि पुरानी फ़ाइलें अपने-आप मिट जाएं. इसके लिए, ऑब्जेक्ट के लाइफ़साइकल मैनेज करना लेख पढ़ें.

अन्य सर्वर

PUT और GET के साथ काम करने वाले किसी भी एचटीटीपी/1.1 सर्वर को, कैश मेमोरी के बैकएंड के तौर पर सेट अप किया जा सकता है. उपयोगकर्ताओं ने Hazelcast, Apache httpd, और AWS S3 जैसे बैकएंड को कैश मेमोरी में सेव करने की सुविधा का इस्तेमाल किया है.

पुष्टि करना

Bazel के वर्शन 0.11.0 में, एचटीटीपी बेसिक ऑथेंटिकेशन की सुविधा जोड़ी गई थी. रिमोट कैश के यूआरएल के ज़रिए, Bazel को उपयोगकर्ता नाम और पासवर्ड दिया जा सकता है. इसका सिंटैक्स https://username:password@hostname.com:port/path है. ध्यान दें कि एचटीटीपी बेसिक ऑथेंटिकेशन, नेटवर्क पर उपयोगकर्ता नाम और पासवर्ड को टेक्स्ट के तौर पर ट्रांसमिट करता है. इसलिए, इसका इस्तेमाल हमेशा एचटीटीपीएस के साथ करना ज़रूरी है.

एचटीटीपी कैश मेमोरी प्रोटोकॉल

Bazel, एचटीटीपी/1.1 के ज़रिए रिमोट कैशिंग की सुविधा देता है. यह प्रोटोकॉल कॉन्सेप्ट के हिसाब से आसान है: बाइनरी डेटा (बीएलओबी) को 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

CAS में SHA256 हैश 15e2b0d3... वाली आउटपुट फ़ाइल अपलोड करने का Bazel अनुरोध इस तरह दिखेगा:

PUT /cache/cas/15e2b0d3c33891ebb0f1ef609ec419420c20e320ce94c65fbc8c3312448eb225 HTTP/1.1
Host: localhost:8080
Accept: */*
Content-Length: 9
Connection: Keep-Alive

0x310x320x330x340x350x360x370x380x39

रिमोट कैश मेमोरी का इस्तेमाल करके Bazel चलाना

किसी सर्वर को रिमोट कैश के तौर पर सेट अप करने के बाद, रिमोट कैश का इस्तेमाल करने के लिए, आपको Bazel कमांड में फ़्लैग जोड़ने होंगे. नीचे कॉन्फ़िगरेशन और उनके फ़्लैग की सूची देखें.

आपको पुष्टि करने की सुविधा भी कॉन्फ़िगर करनी पड़ सकती है. यह सुविधा, चुने गए सर्वर के हिसाब से होती है.

इन फ़्लैग को .bazelrc फ़ाइल में जोड़ा जा सकता है, ताकि Bazel को हर बार चलाने पर आपको इन्हें तय न करना पड़े. अपने प्रोजेक्ट और टीम की ज़रूरतों के हिसाब से, .bazelrc फ़ाइल में फ़्लैग जोड़े जा सकते हैं. यह फ़ाइल:

  • अपनी लोकल मशीन पर
  • आपके प्रोजेक्ट के वर्कस्पेस में, टीम के साथ शेयर किया गया
  • सीआई सिस्टम पर

रिमोट कैश मेमोरी से डेटा पढ़ना और उसमें बदलाव करना

ध्यान रखें कि रिमोट कैश में लिखने की अनुमति किसके पास है. ऐसा हो सकता है कि आपको सिर्फ़ अपने सीआई सिस्टम को रिमोट कैश में डेटा ट्रांसफ़र करने की अनुमति देनी हो.

रिमोट कैश मेमोरी से डेटा पढ़ने और उसमें डेटा लिखने के लिए, इस फ़्लैग का इस्तेमाल करें:

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"],
)

रिमोट कैश मेमोरी से कॉन्टेंट मिटाना

रिमोट कैश से कॉन्टेंट मिटाना, सर्वर को मैनेज करने का हिस्सा है. रिमोट कैश से कॉन्टेंट मिटाने का तरीका, उस सर्वर पर निर्भर करता है जिसे आपने कैश के तौर पर सेट अप किया है. आउटपुट मिटाते समय, पूरी कैश मेमोरी मिटाएं या पुराने आउटपुट मिटाएं.

कैश मेमोरी में सेव किए गए आउटपुट को नामों और हैश के सेट के तौर पर सेव किया जाता है. कॉन्टेंट मिटाते समय, यह पता नहीं चलता कि कौनसी आउटपुट फ़ाइल किस बिल्ड से जुड़ी है.

कैश मेमोरी से कॉन्टेंट मिटाने की ये वजहें हो सकती हैं:

  • कैश मेमोरी में गड़बड़ी होने के बाद, नई कैश मेमोरी बनाना
  • पुराने आउटपुट मिटाकर, इस्तेमाल किए गए स्टोरेज की मात्रा कम करना

यूनिक्स सॉकेट

रिमोट एचटीटीपी कैश, यूनिक्स डोमेन सॉकेट से कनेक्ट करने की सुविधा देता है. यह curl के --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 फ़्लैग का इस्तेमाल करके, बदलाव का पता लगाने की सुविधा चालू की जा सकती है. फ़िलहाल, इस सुविधा से जुड़ी कोई समस्या नहीं है. आने वाले समय में रिलीज़ होने वाले नए वर्शन में, यह सुविधा डिफ़ॉल्ट रूप से चालू हो जाएगी. अपडेट के लिए, [समस्या #3360] देखें. आम तौर पर, बिल्ड के दौरान सोर्स फ़ाइलों में बदलाव करने से बचें.

किसी कार्रवाई में एनवायरमेंट वैरिएबल लीक होना

ऐक्शन की परिभाषा में एनवायरमेंट वैरिएबल शामिल होते हैं. इससे अलग-अलग मशीनों के बीच रिमोट कैश मेमोरी हिट शेयर करने में समस्या आ सकती है. उदाहरण के लिए, अलग-अलग $PATH वैरिएबल वाले एनवायरमेंट, कैश हिट शेयर नहीं करेंगे. कार्रवाई की परिभाषा में, सिर्फ़ वे एनवायरमेंट वैरिएबल शामिल किए जाते हैं जिन्हें --action_env के ज़रिए साफ़ तौर पर अनुमति वाली सूची में शामिल किया गया है. Bazel का Debian/Ubuntu पैकेज, /etc/bazel.bazelrc को इंस्टॉल करने के लिए इस्तेमाल किया जाता है. इसमें एनवायरमेंट वैरिएबल की अनुमति वाली सूची शामिल होती है. जैसे, $PATH. अगर आपको उम्मीद से कम कैश हिट मिल रहे हैं, तो देखें कि आपके एनवायरमेंट में कोई पुरानी /etc/bazel.bazelrc फ़ाइल मौजूद न हो.

Bazel, वर्कस्पेस के बाहर के टूल को ट्रैक नहीं करता है

फ़िलहाल, Bazel किसी वर्कस्पेस के बाहर के टूल को ट्रैक नहीं करता. अगर कोई कार्रवाई /usr/bin/ से कंपाइलर का इस्तेमाल करती है, तो यह समस्या हो सकती है. इसके बाद, अलग-अलग कंपाइलर इंस्टॉल करने वाले दो उपयोगकर्ता, कैश मेमोरी हिट को गलत तरीके से शेयर करेंगे. ऐसा इसलिए होगा, क्योंकि आउटपुट अलग-अलग हैं, लेकिन उनके पास एक ही ऐक्शन हैश है. अपडेट के लिए, समस्या #4558 देखें.

डॉकर कंटेनर में बिल्ड चलाने पर, इन-मेमोरी स्टेट में हुए बदलाव सेव नहीं होते Bazel, सर्वर/क्लाइंट आर्किटेक्चर का इस्तेमाल करता है. भले ही, इसे एक ही डॉकर कंटेनर में चलाया जा रहा हो. सर्वर साइड पर, Bazel इन-मेमोरी स्टेट को बनाए रखता है. इससे बिल्ड तेज़ी से तैयार होते हैं. जब CI जैसे डॉकर कंटेनर में बिल्ड चलाए जाते हैं, तो इन-मेमोरी स्टेट मिट जाती है. इसलिए, रिमोट कैश मेमोरी का इस्तेमाल करने से पहले, Bazel को इसे फिर से बनाना होगा.