หน้านี้ครอบคลุมการแคชระยะไกล การตั้งค่าเซิร์ฟเวอร์เพื่อโฮสต์แคช และการเรียกใช้บิลด์โดยใช้แคชระยะไกล
ทีมนักพัฒนาซอฟต์แวร์และ/หรือระบบการรวมอย่างต่อเนื่อง (CI) ใช้แคชระยะไกลเพื่อแชร์เอาต์พุตของบิลด์ หากบิลด์สามารถทำซ้ำได้ คุณจะนำเอาต์พุตจากเครื่องหนึ่งไปใช้ซ้ำในอีกเครื่องหนึ่งได้อย่างปลอดภัย ซึ่งจะทำให้บิลด์เร็วขึ้นอย่างมาก
ภาพรวม
Bazel จะแบ่งบิลด์ออกเป็นขั้นตอนที่แยกกัน ซึ่งเรียกว่าการดำเนินการ การดำเนินการแต่ละรายการมีอินพุต ชื่อเอาต์พุต บรรทัดคำสั่ง และตัวแปรสภาพแวดล้อม ระบบจะประกาศอินพุตที่จำเป็นและเอาต์พุตที่คาดหวังอย่างชัดเจนสำหรับการดำเนินการแต่ละรายการ
คุณสามารถตั้งค่าเซิร์ฟเวอร์ให้เป็นแคชระยะไกลสำหรับเอาต์พุตของบิลด์ ซึ่งเป็นเอาต์พุตของการดำเนินการเหล่านี้ เอาต์พุตเหล่านี้ประกอบด้วยรายการชื่อไฟล์เอาต์พุตและแฮชของเนื้อหา เมื่อใช้แคชระยะไกล คุณจะนำเอาต์พุตของบิลด์จากบิลด์ของผู้ใช้รายอื่นไปใช้ซ้ำได้แทนที่จะสร้างเอาต์พุตใหม่แต่ละรายการในเครื่อง
วิธีใช้การแคชระยะไกล
- ตั้งค่าเซิร์ฟเวอร์เป็นแบ็กเอนด์ของแคช
- กำหนดค่าบิลด์ Bazel ให้ใช้แคชระยะไกล
- ใช้ Bazel เวอร์ชัน 0.10.0 ขึ้นไป
แคชระยะไกลจะจัดเก็บข้อมูล 2 ประเภท ได้แก่
- แคชการดำเนินการ ซึ่งเป็นการแมปแฮชการดำเนินการกับข้อมูลเมตาของผลการดำเนินการ
- ที่เก็บข้อมูลที่ระบุตำแหน่งตามเนื้อหา (CAS) ของไฟล์เอาต์พุต
โปรดทราบว่าแคชระยะไกลจะจัดเก็บ stdout และ stderr สำหรับการดำเนินการทุกรายการด้วย ดังนั้น การตรวจสอบ stdout/stderr ของ Bazel จึงไม่ใช่สัญญาณที่ดีในการ ประมาณการฮิตของแคช
วิธีที่บิลด์ใช้การแคชระยะไกล
เมื่อตั้งค่าเซิร์ฟเวอร์เป็นแคชระยะไกลแล้ว คุณจะใช้แคชได้หลายวิธี ดังนี้
- อ่านและเขียนไปยังแคชระยะไกล
- อ่านและ/หรือเขียนไปยังแคชระยะไกล ยกเว้นเป้าหมายที่เฉพาะเจาะจง
- อ่านจากแคชระยะไกลเท่านั้น
- ไม่ใช้แคชระยะไกลเลย
เมื่อเรียกใช้บิลด์ Bazel ที่อ่านและเขียนไปยังแคชระยะไกลได้ บิลด์จะทำตามขั้นตอนต่อไปนี้
- Bazel สร้างกราฟของเป้าหมายที่ต้องสร้าง แล้วสร้างรายการการดำเนินการที่จำเป็น การดำเนินการแต่ละรายการมีอินพุตและชื่อไฟล์เอาต์พุตที่ประกาศไว้
- Bazel ตรวจสอบเอาต์พุตของบิลด์ที่มีอยู่ในเครื่องภายในและนำเอาต์พุตที่พบไปใช้ซ้ำ
- Bazel ตรวจสอบเอาต์พุตของบิลด์ที่มีอยู่ในแคช หากพบเอาต์พุต Bazel จะดึงเอาต์พุต ซึ่งเรียกว่าพบแคช
- สำหรับการดำเนินการที่จำเป็นซึ่งไม่พบเอาต์พุต Bazel จะดำเนินการในเครื่องและสร้างเอาต์พุตของบิลด์ที่จำเป็น
- ระบบจะอัปโหลดเอาต์พุตของบิลด์ใหม่ไปยังแคชระยะไกล
การตั้งค่าเซิร์ฟเวอร์เป็นแบ็กเอนด์ของแคช
คุณต้องตั้งค่าเซิร์ฟเวอร์ให้ทำหน้าที่เป็นแบ็กเอนด์ของแคช เซิร์ฟเวอร์ HTTP/1.1 สามารถจัดการข้อมูลของ Bazel เป็นไบต์ที่ทึบแสงได้ ดังนั้นจึงสามารถใช้เซิร์ฟเวอร์ที่มีอยู่จำนวนมากเป็นแบ็กเอนด์การแคชระยะไกลได้ โปรโตคอลการแคช HTTP ของ Bazel เป็นสิ่งที่รองรับการแคชระยะไกล
คุณมีหน้าที่รับผิดชอบในการเลือก ตั้งค่า และดูแลรักษาเซิร์ฟเวอร์แบ็กเอนด์ที่จะจัดเก็บเอาต์พุตที่แคชไว้ เมื่อเลือกเซิร์ฟเวอร์ ให้พิจารณาสิ่งต่อไปนี้
- ความเร็วเครือข่าย เช่น หากทีมของคุณอยู่ในออฟฟิศเดียวกัน คุณอาจต้องการเรียกใช้เซิร์ฟเวอร์ภายในของคุณเอง
- ความปลอดภัย แคชระยะไกลจะมีไบนารีของคุณ ดังนั้นจึงต้องมีความปลอดภัย
- ความสะดวกในการจัดการ เช่น Google Cloud Storage เป็นบริการที่มีการจัดการครบวงจร
มีแบ็กเอนด์มากมายที่ใช้สำหรับแคชระยะไกลได้ ตัวเลือกบางส่วน ได้แก่
nginx
nginx เป็นเว็บเซิร์ฟเวอร์แบบโอเพนซอร์ส โดยสามารถใช้เป็นแคชระยะไกลสำหรับ Bazel ได้ด้วย [โมดูล WebDAV] ใน Debian และ Ubuntu คุณสามารถติดตั้งแพ็กเกจ nginx-extras ได้ ใน macOS nginx จะพร้อมใช้งานผ่าน Homebrew ดังนี้
brew tap denji/nginxbrew 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-remote
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 เป็นแคช
สร้าง Bucket พื้นที่เก็บข้อมูล ตรวจสอบว่าคุณเลือกตำแหน่ง Bucket ที่อยู่ใกล้คุณที่สุด เนื่องจากแบนด์วิดท์เครือข่ายมีความสำคัญต่อแคชระยะไกล
สร้างบัญชีบริการเพื่อให้ Bazel ตรวจสอบสิทธิ์กับ Cloud Storage ดู การสร้างบัญชีบริการ
สร้างคีย์ลับ JSON แล้วส่งคีย์ดังกล่าวไปยัง Bazel เพื่อตรวจสอบสิทธิ์ จัดเก็บคีย์อย่างปลอดภัย เนื่องจากทุกคนที่มีคีย์จะอ่านและเขียนข้อมูลที่กำหนดเองไปยัง/จาก Bucket ของ GCS ได้
เชื่อมต่อกับ Cloud Storage โดยเพิ่มแฟล็กต่อไปนี้ลงในคำสั่ง Bazel
- ส่ง URL ต่อไปนี้ไปยัง Bazel โดยใช้แฟล็ก:
--remote_cache=https://storage.googleapis.com/bucket-nameโดยที่bucket-nameคือชื่อ Bucket พื้นที่เก็บข้อมูล - ส่งคีย์การตรวจสอบสิทธิ์โดยใช้แฟล็ก
--google_credentials=/path/to/your/secret-key.jsonหรือ--google_default_credentialsเพื่อใช้ การตรวจสอบสิทธิ์แอปพลิเคชัน
- ส่ง URL ต่อไปนี้ไปยัง Bazel โดยใช้แฟล็ก:
คุณสามารถกำหนดค่า 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
เรียกใช้ Bazel โดยใช้แคชระยะไกล
เมื่อตั้งค่าเซิร์ฟเวอร์เป็นแคชระยะไกลแล้ว หากต้องการใช้แคชระยะไกล คุณต้องเพิ่มแฟล็กลงในคำสั่ง Bazel ดูรายการการกำหนดค่าและแฟล็กที่เกี่ยวข้องด้านล่าง
นอกจากนี้ คุณอาจต้องกำหนดค่าการตรวจสอบสิทธิ์ ซึ่งจะขึ้นอยู่กับเซิร์ฟเวอร์ที่คุณเลือก
คุณอาจต้องการเพิ่มแฟล็กเหล่านี้ในไฟล์ .bazelrc เพื่อไม่ให้ต้องระบุแฟล็กทุกครั้งที่เรียกใช้ Bazel คุณสามารถเพิ่มแฟล็กลงในไฟล์ .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 ลักษณะการทำงานจะคล้ายกับแฟล็ก --unix-socket ของ curl ใช้คำสั่งต่อไปนี้เพื่อกำหนดค่าซ็อกเก็ตโดเมน Unix
build --remote_cache=http://your.host:port
build --remote_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 เท่านั้นที่จะรวมอยู่ในคำจำกัดความของการดำเนินการ แพ็กเกจ Debian/Ubuntu ของ Bazel เคยติดตั้ง /etc/bazel.bazelrc พร้อมรายการตัวแปรสภาพแวดล้อมที่อนุญาตพิเศษ ซึ่งรวมถึง $PATH หากคุณได้รับฮิตของแคชน้อยกว่าที่คาดไว้ ให้ตรวจสอบว่าสภาพแวดล้อมของคุณไม่มีไฟล์ /etc/bazel.bazelrc เก่า
Bazel ไม่ติดตามเครื่องมือภายนอกพื้นที่ทำงาน
ปัจจุบัน Bazel ไม่ติดตามเครื่องมือภายนอกพื้นที่ทำงาน ซึ่งอาจเป็นปัญหาได้หากการดำเนินการใช้คอมไพเลอร์จาก /usr/bin/ จากนั้น ผู้ใช้ 2 รายที่ติดตั้งคอมไพเลอร์ต่างกันจะแชร์ฮิตของแคชอย่างไม่ถูกต้อง เนื่องจากเอาต์พุตต่างกันแต่มีแฮชการดำเนินการเดียวกัน ดูข้อมูลอัปเดตได้ที่
ปัญหา #4558
สถานะที่เพิ่มขึ้นในหน่วยความจำจะหายไปเมื่อเรียกใช้บิลด์ภายในคอนเทนเนอร์ Docker Bazel ใช้สถาปัตยกรรมเซิร์ฟเวอร์/ไคลเอ็นต์แม้ว่าจะเรียกใช้ในคอนเทนเนอร์ Docker เดียวก็ตาม ในฝั่งเซิร์ฟเวอร์ Bazel จะรักษาสถานะในหน่วยความจำซึ่งจะช่วยเร่งความเร็วของบิลด์ เมื่อเรียกใช้บิลด์ภายในคอนเทนเนอร์ Docker เช่น ใน CI สถานะในหน่วยความจำจะหายไปและ Bazel ต้องสร้างสถานะใหม่ก่อนที่จะใช้แคชระยะไกล
ลิงก์ภายนอก
Your Build in a Datacenter: ทีม Bazel ได้พูดคุยเกี่ยวกับการพูดคุยเกี่ยวกับการแคชและการดำเนินการระยะไกลที่ FOSDEM 2018
Faster Bazel builds with remote caching: a benchmark: Nicolò Valigi เขียน บล็อกโพสต์ ที่เขาทำการเปรียบเทียบการแคชระยะไกลใน Bazel