การแคชจากระยะไกล

รายงานปัญหา ดูแหล่งที่มา ตอนกลางคืน · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

หน้านี้จะครอบคลุมการแคชระยะไกล การตั้งค่าเซิร์ฟเวอร์เพื่อโฮสต์แคช และ กำลังใช้บิลด์โดยใช้แคชระยะไกล

ทีมนักพัฒนาแอปใช้แคชระยะไกลและ/หรือการผสานรวมอย่างต่อเนื่อง (CI) สำหรับแชร์เอาต์พุตของบิลด์ หากบิลด์ของคุณทำซ้ำได้ เอาต์พุตจากเครื่องหนึ่งสามารถนำมาใช้ซ้ำอย่างปลอดภัยกับอีกเครื่องหนึ่งได้ ซึ่ง ทำให้งานสร้างเร็วขึ้นมาก

ภาพรวม

Bazel แบ่งโครงสร้างออกเป็นขั้นตอนต่างๆ ที่แยกจากกัน ซึ่งเรียกว่าการกระทำ การดำเนินการแต่ละรายการ มีอินพุต ชื่อเอาต์พุต บรรทัดคำสั่ง และตัวแปรสภาพแวดล้อม จำเป็น ระบบจะประกาศอินพุตและเอาต์พุตที่คาดไว้อย่างชัดเจนสำหรับการดำเนินการแต่ละรายการ

คุณตั้งค่าเซิร์ฟเวอร์เป็นแคชระยะไกลสำหรับเอาต์พุตของบิลด์ได้ ซึ่งมีดังต่อไปนี้ เอาต์พุตจากการทำงาน เอาต์พุตเหล่านี้จะประกอบด้วยรายการชื่อไฟล์เอาต์พุตและ แฮชเนื้อหา เมื่อใช้แคชระยะไกล คุณจะใช้เอาต์พุตของบิลด์ซ้ำได้ จากบิลด์ของผู้ใช้อีกราย แทนการสร้างเอาต์พุตใหม่แต่ละรายการในเครื่อง

วิธีใช้การแคชระยะไกล

  • ตั้งค่าเซิร์ฟเวอร์เป็นแบ็กเอนด์ของแคช
  • กำหนดค่าบิลด์ Bazel เพื่อใช้แคชระยะไกล
  • ใช้ Bazel เวอร์ชัน 0.10.0 ขึ้นไป

แคชระยะไกลจะจัดเก็บข้อมูล 2 ประเภทดังนี้

  • แคชการดำเนินการ ซึ่งเป็นการแมปแฮชการดำเนินการกับข้อมูลเมตาของผลลัพธ์การดำเนินการ
  • พื้นที่เก็บข้อมูลที่ระบุเนื้อหา (CAS) ของไฟล์เอาต์พุต

โปรดทราบว่าแคชระยะไกลจะจัดเก็บ stdout และ stderr เพิ่มเติมสำหรับทุกๆ การดำเนินการ การตรวจสอบ stdout/stderr ของ Bazel ดังนั้นจึงไม่ใช่สัญญาณที่ดีสำหรับ การประมาณการพบแคช

วิธีที่บิลด์ใช้การแคชระยะไกล

เมื่อตั้งค่าเซิร์ฟเวอร์เป็นแคชระยะไกลแล้ว คุณจะใช้แคชในหลาย ด้วยวิธีต่อไปนี้

  • อ่านและเขียนไปยังแคชระยะไกล
  • อ่านและ/หรือเขียนไปยังแคชระยะไกล ยกเว้นเป้าหมายเฉพาะ
  • อ่านจากแคชระยะไกลเท่านั้น
  • ไม่ใช้แคชระยะไกลเลย

เมื่อคุณเรียกใช้บิลด์ Bazel ที่อ่านและเขียนไปยังแคชระยะไกลได้ บิลด์ดังกล่าวจะทำตามขั้นตอนต่อไปนี้

  1. Bazel สร้างกราฟของเป้าหมายที่ต้องสร้างขึ้น แล้วสร้าง รายการการดำเนินการที่จำเป็น การดำเนินการแต่ละรายการเหล่านี้ได้ประกาศอินพุตแล้ว และชื่อไฟล์เอาต์พุต
  2. Bazel ตรวจสอบเครื่องของคุณเองเพื่อหาเอาต์พุตของบิลด์ที่มีอยู่และนำไปใช้งานซ้ำ ที่พบ
  3. Bazel ตรวจสอบแคชสำหรับเอาต์พุตของบิลด์ที่มีอยู่ หากพบผลลัพธ์ที่ต้องการ Bazel เรียกเอาต์พุต นี่เป็นการพบแคช
  4. สำหรับการทำงานที่จำเป็นซึ่งไม่พบเอาต์พุต Bazel จะเรียกใช้ ภายในเครื่องและสร้างเอาต์พุตของบิลด์ที่จำเป็น
  5. อัปโหลดเอาต์พุตของบิลด์ใหม่ไปยังแคชระยะไกลแล้ว

การตั้งค่าเซิร์ฟเวอร์เป็นแบ็กเอนด์ของแคช

คุณต้องตั้งค่าเซิร์ฟเวอร์ให้ทำหน้าที่เป็นแบ็กเอนด์ของแคช HTTP/1.1 เซิร์ฟเวอร์สามารถจัดการข้อมูลของ Bazel ในแบบไบต์ทึบ และเซิร์ฟเวอร์ที่มีอยู่จำนวนมาก สามารถใช้เป็นแบ็กเอนด์การแคชระยะไกล บาเซล โปรโตคอลการแคช HTTP คือสิ่งที่รองรับจากระยะไกล การแคช

คุณมีหน้าที่รับผิดชอบในการเลือก ตั้งค่า และดูแลรักษาแบ็กเอนด์ เซิร์ฟเวอร์ที่จะจัดเก็บเอาต์พุตที่แคชไว้ เมื่อเลือกเซิร์ฟเวอร์ ให้พิจารณาถึงสิ่งต่อไปนี้

  • ความเร็วของเครือข่าย ตัวอย่างเช่น ถ้าทีมของคุณอยู่ในสำนักงานเดียวกัน คุณอาจ ต้องการใช้งานเซิร์ฟเวอร์ภายในของคุณเอง
  • ความปลอดภัย แคชระยะไกลจะมีไบนารีของคุณ ดังนั้นจึงต้องมีความปลอดภัย
  • การจัดการที่ง่ายดาย เช่น Google Cloud Storage เป็นบริการที่มีการจัดการครบวงจร

มีแบ็กเอนด์มากมายที่สามารถใช้สำหรับแคชระยะไกล ตัวเลือกบางรายการ รวมข้อมูลต่อไปนี้

nginx

nginx เป็นเว็บเซิร์ฟเวอร์แบบโอเพนซอร์ส ด้วย[โมดูล WebDAV] ทำให้คุณสามารถ ใช้เป็นแคชระยะไกลสำหรับ Bazel ใน Debian และ Ubuntu คุณสามารถติดตั้ง แพ็กเกจ nginx-extras ใน macOS nginx พร้อมให้ใช้งานผ่าน Homeภาษาของ

brew tap denji/nginx
brew install nginx-full --with-webdav

ด้านล่างคือตัวอย่างการกำหนดค่าสำหรับ nginx โปรดทราบว่าคุณจะต้อง เปลี่ยน /path/to/cache/dir เป็นไดเรกทอรีที่ถูกต้องที่ nginx มีสิทธิ์ เพื่อเขียนและอ่านได้ คุณอาจต้องเปลี่ยนตัวเลือก client_max_body_size เป็น จะมีค่ามากขึ้นหากคุณมีไฟล์เอาต์พุตขนาดใหญ่ เซิร์ฟเวอร์จะกำหนดให้มี การกำหนดค่า เช่น การตรวจสอบสิทธิ์

ตัวอย่างการกำหนดค่าสำหรับส่วน server ใน nginx.conf

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

bazel-remote เป็นแคชบิลด์ระยะไกลแบบโอเพนซอร์สที่คุณใช้ได้ใน โครงสร้างพื้นฐานของคุณ มีการนำโซลูชันไปใช้ในเวอร์ชันที่ใช้งานจริงเรียบร้อยแล้วเมื่อ บริษัทหลายแห่งตั้งแต่ต้นปี 2018 โปรดทราบว่าโปรเจ็กต์ Bazel ไม่ได้ให้การสนับสนุนด้านเทคนิคสําหรับ bazel-remote

แคชนี้จัดเก็บเนื้อหาในดิสก์และยังมีการเก็บข้อมูลขยะด้วย เพื่อบังคับใช้ขีดจำกัดพื้นที่เก็บข้อมูลสูงสุดและล้างอาร์ติแฟกต์ที่ไม่ได้ใช้ แคชจะ มีให้บริการเป็น [รูปภาพ Docker] และโค้ดของสไลด์นี้มีอยู่ใน GitHub รองรับทั้ง API แคชระยะไกลของ REST และ gRPC

โปรดดูที่ GitHub เพื่อดูวิธีการใช้งาน

Google Cloud Storage

[Google Cloud Storage] เป็นที่จัดเก็บออบเจ็กต์ที่มีการจัดการครบวงจรซึ่งมอบ HTTP API ที่เข้ากันได้กับโปรโตคอลการแคชระยะไกลของ Bazel ต้องการ คุณมีบัญชี Google Cloud ที่เปิดใช้การเรียกเก็บเงิน

วิธีใช้ Cloud Storage เป็นแคช

  1. สร้างที่เก็บข้อมูลของพื้นที่เก็บข้อมูล ตรวจสอบว่าคุณเลือกตำแหน่งที่เก็บข้อมูลที่อยู่ใกล้กับคุณที่สุด เช่น แบนด์วิดท์ของเครือข่าย เป็นสิ่งสำคัญสำหรับแคชระยะไกล

  2. สร้างบัญชีบริการสำหรับ Bazel เพื่อตรวจสอบสิทธิ์กับ Cloud Storage โปรดดู การสร้างบัญชีบริการ

  3. สร้างคีย์ JSON ลับแล้วส่งไปให้ Bazel ตรวจสอบสิทธิ์ ร้านค้า คีย์ได้อย่างปลอดภัย เนื่องจากทุกคนที่มีคีย์จะอ่านและเขียนข้อมูลที่กำหนดเองได้ to/จากที่เก็บข้อมูล GCS

  4. เชื่อมต่อกับ Cloud Storage โดยเพิ่มแฟล็กต่อไปนี้ในคำสั่ง Bazel

    • ส่งต่อ URL ต่อไปนี้ไปยัง Bazel โดยใช้แฟล็ก --remote_cache=https://storage.googleapis.com/bucket-name โดยที่ bucket-name คือชื่อของที่เก็บข้อมูลของพื้นที่เก็บข้อมูล
    • ส่งคีย์การตรวจสอบสิทธิ์โดยใช้แฟล็ก: --google_credentials=/path/to/your/secret-key.json หรือ --google_default_credentials เพื่อใช้ Application Authentication
  5. คุณกำหนดค่า Cloud Storage ให้ลบไฟล์เก่าโดยอัตโนมัติได้ โดยดูที่ การจัดการวงจรของออบเจ็กต์

เซิร์ฟเวอร์อื่นๆ

คุณสามารถตั้งค่าเซิร์ฟเวอร์ HTTP/1.1 ที่สนับสนุน PUT และ GET เป็น แบ็กเอนด์ ผู้ใช้ได้รายงานว่าประสบความสำเร็จกับแบ็กเอนด์การแคช เช่น Hazelcast Apache httpd และ AWS S3

การตรวจสอบสิทธิ์

ตั้งแต่เวอร์ชัน 0.11.0 ได้มีการเพิ่มการสนับสนุนการตรวจสอบสิทธิ์พื้นฐานของ HTTP ไปยัง Bazel คุณส่งชื่อผู้ใช้และรหัสผ่านไปยัง Bazel ผ่าน URL ของแคชระยะไกลได้ ไวยากรณ์คือ https://username:password@hostname.com:port/path โปรดทราบว่า การตรวจสอบสิทธิ์พื้นฐานของ HTTP จะส่งชื่อผู้ใช้และรหัสผ่านในรูปแบบข้อความธรรมดาผ่าน เครือข่าย และ ดังนั้นจึงจำเป็นที่จะต้องใช้กับ HTTPS ทุกครั้ง

โปรโตคอลการแคช HTTP

Bazel รองรับการแคชระยะไกลผ่าน HTTP/1.1 โปรโตคอลมีหลักการที่เรียบง่าย ดังนี้ ข้อมูลไบนารี (BLOB) มีการอัปโหลดผ่านคำขอ PUT และดาวน์โหลดผ่านคำขอ GET ข้อมูลเมตาของผลการดำเนินการจัดเก็บอยู่ในเส้นทาง /ac/ และจัดเก็บไฟล์เอาต์พุตไว้ ใต้เส้นทาง /cas/

ตัวอย่างเช่น ลองพิจารณาแคชระยะไกลที่ทำงานภายใต้ http://localhost:8080/cache คำขอ Bazel เพื่อดาวน์โหลดข้อมูลเมตาของผลการดำเนินการสำหรับการดำเนินการที่มี SHA256 แฮช 01ba4719... จะมีลักษณะดังนี้

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

คำเตือน: สร้างโดยไม่ใช้ไบต์ ไม่สามารถทำงานร่วมกับแคช HTTP หากต้องการเพิ่มประสิทธิภาพสูงสุด ลองใช้แคช gRPC แทนนะ

เรียกใช้ Bazel โดยใช้แคชระยะไกล

เมื่อตั้งค่าเซิร์ฟเวอร์เป็นแคชระยะไกล เพื่อใช้แคชระยะไกล ต้องเพิ่มแฟล็กในคำสั่ง Bazel ของคุณ ดูรายการการกำหนดค่าและ ธงของตนที่ด้านล่าง

นอกจากนี้ คุณอาจต้องกำหนดค่าการตรวจสอบสิทธิ์ ซึ่งเป็นข้อมูลเฉพาะ เซิร์ฟเวอร์ที่เลือก

คุณอาจต้องการเพิ่ม Flag เหล่านี้ในไฟล์ .bazelrc เพื่อไม่ให้ คุณต้องระบุไว้ทุกครั้งที่คุณเรียกใช้ Bazel ทั้งนี้ขึ้นอยู่กับโปรเจ็กต์และ ของทีมแบบไดนามิก คุณจะสามารถเพิ่ม Flag ในไฟล์ .bazelrc ที่มีลักษณะดังนี้

  • ในเครื่องของคุณ
  • แชร์กับทีมในพื้นที่ทำงานของโปรเจ็กต์
  • ในระบบ CI

อ่านและเขียนไปยังแคชระยะไกล

ตรวจสอบว่าใครเขียนลงในแคชระยะไกลได้บ้าง คุณอาจต้องการ เฉพาะระบบ 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 ลักษณะการทำงาน คล้ายกับ Flag --unix-socket ของ Curl ใช้รายการต่อไปนี้เพื่อกำหนดค่า Unix ซ็อกเก็ตโดเมน:

   build --remote_cache=http://your.host:port
   build --remote_proxy=unix:/path/to/socket

ฟีเจอร์นี้ไม่รองรับใน Windows

ดิสก์แคช

Bazel ใช้ไดเรกทอรีในระบบไฟล์เป็นแคชระยะไกลได้ นี่คือ มีประโยชน์ในการแชร์อาร์ติแฟกต์ของบิลด์เมื่อเปลี่ยน Branch และ/หรือขณะทำงาน บนพื้นที่ทำงานหลายแห่งของโปรเจ็กต์เดียวกัน เช่น จุดชำระเงินหลายรายการ ตั้งแต่ปี Bazel ไม่ได้รวบรวมข้อมูลไดเรกทอรี คุณอาจต้องทำให้ไดเรกทอรี การทำความสะอาดไดเรกทอรีนี้เป็นระยะ เปิดใช้ดิสก์แคชดังนี้

build --disk_cache=path/to/build/cache

คุณส่งเส้นทางเฉพาะผู้ใช้ไปยังแฟล็ก --disk_cache ได้โดยใช้ชื่อแทน ~ (Bazel จะแทนที่ไดเรกทอรีหน้าแรกของผู้ใช้ปัจจุบัน) มีประโยชน์ เมื่อเปิดใช้ดิสก์แคชสำหรับผู้พัฒนาโปรเจ็กต์ทุกคนผ่าน เช็คอิน .bazelrc ไฟล์

ปัญหาที่ทราบ

ป้อนข้อมูลการแก้ไขไฟล์ระหว่างบิลด์

เมื่อไฟล์อินพุตมีการแก้ไขระหว่างการสร้าง Bazel อาจอัปโหลดที่ไม่ถูกต้อง ผลลัพธ์ไปยังแคชระยะไกล คุณเปิดใช้การตรวจหาการเปลี่ยนแปลงได้ด้วย ธง--experimental_guard_against_concurrent_changes เรียบร้อย ไม่ใช่ปัญหาที่ทราบแล้ว และจะเปิดใช้โดยค่าเริ่มต้นในรุ่นถัดไป ดูการอัปเดตใน [ปัญหา #3360] โดยทั่วไปแล้ว ให้หลีกเลี่ยงการแก้ไขไฟล์ต้นฉบับในระหว่าง งานสร้าง

ตัวแปรสภาพแวดล้อมรั่วไหลสู่การทำงาน

คำจำกัดความการดำเนินการมีตัวแปรสภาพแวดล้อม นี่อาจเป็นปัญหาสำหรับ แชร์การพบแคชระยะไกลข้ามเครื่องได้ ตัวอย่างเช่น สภาพแวดล้อมที่มี ตัวแปร $PATH ที่ต่างกันจะไม่แชร์ Hit ของแคช เฉพาะตัวแปรสภาพแวดล้อม รายการที่อนุญาตอย่างชัดแจ้งผ่าน --action_env รวมอยู่ในการดำเนินการ ของเรา แพ็กเกจ Debian/Ubuntu ของ Bazel ที่ใช้ติดตั้ง /etc/bazel.bazelrc ด้วยรายการที่อนุญาตพิเศษของตัวแปรสภาพแวดล้อม ซึ่งรวมถึง $PATH หากคุณกำลัง พบแคชน้อยกว่าที่คาดไว้ โปรดตรวจสอบว่าสภาพแวดล้อมไม่มี /etc/bazel.bazelrc ไฟล์

Bazel ไม่ติดตามเครื่องมือนอกพื้นที่ทำงาน

ขณะนี้ Bazel ไม่ได้ติดตามเครื่องมือนอกพื้นที่ทำงาน ค่านี้อาจเป็น ตัวอย่างเช่น หากการดำเนินการใช้คอมไพเลอร์จาก /usr/bin/ จากนั้นให้ทำดังนี้ ผู้ใช้ 2 รายที่ติดตั้งคอมไพเลอร์ไว้แตกต่างกันจะแชร์ Hit ของแคชอย่างไม่ถูกต้อง เนื่องจากเอาต์พุตแตกต่างกัน แต่มีแฮชการดำเนินการเหมือนกัน โปรดดู ปัญหา #4558 สำหรับการอัปเดต

สถานะในหน่วยความจำที่เพิ่มขึ้นหายไปเมื่อเรียกใช้บิลด์ภายในคอนเทนเนอร์ Docker Bazel ใช้สถาปัตยกรรมของเซิร์ฟเวอร์/ไคลเอ็นต์แม้จะทำงานในคอนเทนเนอร์ Docker เดี่ยว ในฝั่งเซิร์ฟเวอร์ Bazel จะมีสถานะในหน่วยความจำซึ่งช่วยเร่งการสร้างให้เร็วขึ้น เมื่อเรียกใช้บิลด์ภายในคอนเทนเนอร์ Docker เช่น ใน CI สถานะในหน่วยความจำจะหายไป และ Bazel จะต้องสร้างใหม่ ก่อนจึงจะใช้แคชระยะไกล