หน้านี้จะครอบคลุมการแคชระยะไกล การตั้งค่าเซิร์ฟเวอร์เพื่อโฮสต์แคช และการเรียกใช้บิลด์โดยใช้แคชระยะไกล
ทีมนักพัฒนาซอฟต์แวร์และ/หรือระบบการผสานรวมอย่างต่อเนื่อง (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 เป็นเว็บเซิร์ฟเวอร์แบบโอเพนซอร์ส โดยใช้[โมดูล 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-remote
bazel-remote คือแคชการบิลด์ระยะไกลแบบโอเพนซอร์สที่คุณใช้ในโครงสร้างพื้นฐานได้ มีการนำเครื่องมือนี้ไปใช้ในเวอร์ชันที่ใช้งานจริง ในหลายบริษัทตั้งแต่ต้นปี 2018 โปรดทราบว่าโปรเจ็กต์ Bazel ไม่มีการสนับสนุนด้านเทคนิคสำหรับ bazel-remote
แคชนี้จะจัดเก็บเนื้อหาไว้ในดิสก์และยังมีการเก็บขยะเพื่อบังคับใช้ขีดจำกัดพื้นที่เก็บข้อมูลสูงสุดและล้างอาร์ติแฟกต์ที่ไม่ได้ใช้ แคชมีให้บริการเป็น [docker image] และโค้ดของแคชมีอยู่ใน GitHub รองรับทั้ง API แคชระยะไกลของ REST และ gRPC
ดูวิธีการใช้งานได้ที่หน้า GitHub
Google Cloud Storage
[Google Cloud Storage] เป็นที่เก็บออบเจ็กต์ที่มีการจัดการครบวงจรซึ่งมี HTTP API ที่เข้ากันได้กับโปรโตคอลการแคชระยะไกลของ Bazel โดยคุณต้องมีบัญชี Google Cloud ที่เปิดใช้การเรียกเก็บเงิน
วิธีใช้ Cloud Storage เป็นแคช
สร้างที่เก็บข้อมูล ตรวจสอบว่าคุณเลือกตำแหน่งที่เก็บข้อมูลซึ่งอยู่ใกล้กับคุณมากที่สุด เนื่องจากแบนด์วิดท์ของเครือข่ายมีความสำคัญต่อแคชระยะไกล
สร้างบัญชีบริการสำหรับ Bazel เพื่อตรวจสอบสิทธิ์กับ Cloud Storage โปรดดูหัวข้อการสร้างบัญชีบริการ
สร้างคีย์ JSON ลับแล้วส่งไปให้ Bazel ตรวจสอบสิทธิ์ เก็บคีย์อย่างปลอดภัย เนื่องจากทุกคนที่มีคีย์จะอ่านและเขียนข้อมูลใดก็ได้ไปยัง/จากที่เก็บข้อมูล GCS
เชื่อมต่อกับ Cloud Storage โดยเพิ่ม Flag ต่อไปนี้ลงในคำสั่ง Bazel
- ส่ง URL ต่อไปนี้ไปยัง Bazel โดยใช้ Flag
--remote_cache=https://storage.googleapis.com/bucket-name
โดยที่bucket-name
คือชื่อที่เก็บข้อมูล - ส่งคีย์การตรวจสอบสิทธิ์โดยใช้ Flag:
--google_credentials=/path/to/your/secret-key.json
หรือ--google_default_credentials
เพื่อใช้การตรวจสอบสิทธิ์แอปพลิเคชัน
- ส่ง URL ต่อไปนี้ไปยัง Bazel โดยใช้ Flag
คุณกำหนดค่า Cloud Storage ให้ลบไฟล์เก่าโดยอัตโนมัติได้ โปรดดูวิธีการที่หัวข้อการจัดการวงจรออบเจ็กต์
เซิร์ฟเวอร์อื่นๆ
คุณสามารถตั้งค่าเซิร์ฟเวอร์ HTTP/1.1 ที่รองรับ PUT และ GET เป็นแบ็กเอนด์ของแคชได้ ผู้ใช้รายงานว่าประสบความสำเร็จกับแบ็กเอนด์การแคช เช่น Hazelcast, Apache httpd และ AWS S3
การตรวจสอบสิทธิ์
ตั้งแต่เวอร์ชัน 0.11.0 เป็นต้นไป Bazel ได้เพิ่มการรองรับการตรวจสอบสิทธิ์พื้นฐานของ HTTP
คุณส่งชื่อผู้ใช้และรหัสผ่านไปยัง 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 โดยใช้แคชระยะไกล
เมื่อตั้งค่าเซิร์ฟเวอร์เป็นแคชระยะไกลแล้ว หากต้องการใช้แคชระยะไกล คุณจะต้องเพิ่ม Flag ลงในคำสั่ง Bazel ดูรายการการกําหนดค่าและ Flag ได้ที่ด้านล่าง
คุณอาจต้องกำหนดค่าการตรวจสอบสิทธิ์ที่ใช้เฉพาะกับเซิร์ฟเวอร์ที่เลือก
คุณอาจเพิ่ม Flag เหล่านี้ในไฟล์ .bazelrc
เพื่อจะได้ไม่ต้องระบุทุกครั้งที่เรียกใช้ Bazel คุณเพิ่มการแจ้งเตือนลงในไฟล์ .bazelrc
ต่อไปนี้ได้ โดยขึ้นอยู่กับโปรเจ็กต์และลักษณะการทำงานของทีม
- ในเครื่องของคุณ
- แชร์กับทีมในพื้นที่ทำงานของโปรเจ็กต์
- ในระบบ CI
อ่านและเขียนลงในแคชระยะไกล
โปรดระมัดระวังในการกำหนดผู้ที่มีสิทธิ์เขียนลงในแคชระยะไกล คุณอาจต้องการเฉพาะระบบ CI เท่านั้นที่สามารถเขียนไปยังแคชระยะไกลได้
ใช้แฟล็กต่อไปนี้เพื่ออ่านและเขียนไปยังแคชระยะไกล
build --remote_cache=http://your.host:port
นอกจาก HTTP
แล้ว ระบบยังรองรับโปรโตคอล HTTPS
, grpc
, grpcs
ด้วย
ใช้ Flag ต่อไปนี้เพิ่มเติมจาก Flag ด้านบนเพื่ออ่านจากแคชระยะไกลเท่านั้น
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_cache_proxy=unix:/path/to/socket
ฟีเจอร์นี้ไม่รองรับใน Windows
ดิสก์แคช
Bazel สามารถใช้ไดเรกทอรีในระบบไฟล์เป็นแคชระยะไกลได้ ซึ่งมีประโยชน์สำหรับการแชร์อาร์ติแฟกต์การสร้างเมื่อเปลี่ยนสาขาและ/หรือทํางานในเวิร์กスペースหลายแห่งของโปรเจ็กต์เดียวกัน เช่น การเช็คเอาต์หลายรายการ เปิดใช้แคชดิสก์โดยทำดังนี้
build --disk_cache=path/to/build/cache
คุณสามารถส่งเส้นทางเฉพาะผู้ใช้ไปยัง Flag --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 อาจอัปโหลดผลลัพธ์ที่ไม่ถูกต้องไปยังแคชระยะไกล คุณสามารถเปิดใช้การตรวจหาการเปลี่ยนแปลงได้ด้วย Flag --experimental_guard_against_concurrent_changes
ไม่มีปัญหาที่ทราบและจะเปิดใช้โดยค่าเริ่มต้นในรุ่นในอนาคต
ดูการอัปเดตใน [ปัญหา #3360] โดยทั่วไป โปรดหลีกเลี่ยงการแก้ไขไฟล์ต้นฉบับระหว่างการสร้าง
ตัวแปรสภาพแวดล้อมรั่วไหลสู่การทำงาน
คำจำกัดความการดำเนินการมีตัวแปรสภาพแวดล้อม ซึ่งอาจทำให้เกิดปัญหาในการแชร์ Hit ของแคชระยะไกลในเครื่องต่างๆ ตัวอย่างเช่น สภาพแวดล้อมที่มีตัวแปร $PATH
ต่างกันจะไม่แชร์รายการที่ตรงกันในแคช มีเฉพาะตัวแปรสภาพแวดล้อมที่อนุญาตพิเศษอย่างชัดแจ้งผ่าน --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 ต้องสร้างใหม่ก่อนใช้แคชระยะไกล
ลิงก์ภายนอก
บิลด์ของคุณในดาต้าเซ็นเตอร์: ทีม Bazel ได้บรรยายเกี่ยวกับการแคชและการดำเนินการระยะไกลที่ FOSDEM 2018
การสร้าง Bazel ที่เร็วขึ้นโดยใช้การแคชจากระยะไกล: Nicolò Valigi เขียนบล็อกโพสต์ที่เขาใช้ในการเปรียบเทียบการแคชจากระยะไกลใน Bazel