หน้านี้ครอบคลุมการแคชระยะไกล การตั้งค่าเซิร์ฟเวอร์เพื่อโฮสต์แคช และ การเรียกใช้บิลด์โดยใช้แคชระยะไกล
แคชระยะไกลใช้โดยทีมนักพัฒนาซอฟต์แวร์และ/หรือระบบการรวมอย่างต่อเนื่อง (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 ได้ผ่าน Homebrew โดยทำดังนี้
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] และโค้ดของแคชพร้อมให้บริการบน GitHub ระบบรองรับทั้ง REST และ gRPC Remote Cache API
ดูวิธีการใช้งานได้ที่หน้าGitHub
Google Cloud Storage
[Google Cloud Storage] คือที่เก็บข้อมูลออบเจ็กต์ที่มีการจัดการเต็มรูปแบบซึ่งมี HTTP API ที่เข้ากันได้กับโปรโตคอลการแคชระยะไกลของ Bazel โดยคุณต้องมีบัญชี Google Cloud ที่เปิดใช้การเรียกเก็บเงิน
หากต้องการใช้ Cloud Storage เป็นแคช ให้ทำดังนี้
สร้างที่เก็บข้อมูล ตรวจสอบว่าคุณเลือกตำแหน่งที่เก็บข้อมูลที่ใกล้กับคุณมากที่สุด เนื่องจากแบนด์วิดท์เครือข่าย มีความสำคัญต่อแคชระยะไกล
สร้างบัญชีบริการสำหรับ Bazel เพื่อตรวจสอบสิทธิ์กับ Cloud Storage ดูการสร้างบัญชีบริการ
สร้างคีย์ JSON ลับ แล้วส่งไปยัง Bazel เพื่อการตรวจสอบสิทธิ์ จัดเก็บคีย์อย่างปลอดภัย เนื่องจากทุกคนที่มีคีย์จะอ่านและเขียนข้อมูลที่กำหนดเอง ไปยัง/จากที่เก็บข้อมูล GCS ของคุณได้
เชื่อมต่อกับ 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
เพื่อใช้การตรวจสอบสิทธิ์แอปพลิเคชัน
- ส่ง URL ต่อไปนี้ไปยัง Bazel โดยใช้แฟล็ก
คุณสามารถกำหนดค่า 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 โดยใช้แคชระยะไกล
เมื่อตั้งค่าเซิร์ฟเวอร์เป็นแคชระยะไกลแล้ว หากต้องการใช้แคชระยะไกล คุณ ต้องเพิ่มแฟลกลงในคำสั่ง Bazel ดูรายการการกำหนดค่าและ แฟล็กของการกำหนดค่าเหล่านั้นได้ที่ด้านล่าง
นอกจากนี้ คุณอาจต้องกำหนดค่าการตรวจสอบสิทธิ์ซึ่งเฉพาะเจาะจงกับเซิร์ฟเวอร์ที่คุณเลือก
คุณอาจต้องการเพิ่มแฟล็กเหล่านี้ในไฟล์ .bazelrc
เพื่อไม่
ต้องระบุทุกครั้งที่เรียกใช้ Bazel คุณเพิ่ม Flag ลงในไฟล์ .bazelrc
ได้โดยขึ้นอยู่กับโปรเจ็กต์และ
การทำงานร่วมกันของทีม
- ในเครื่องภายใน
- ในพื้นที่ทำงานของโปรเจ็กต์ที่แชร์กับทีม
- ในระบบ CI
อ่านและเขียนไปยังแคชระยะไกล
โปรดระมัดระวังในการให้สิทธิ์เขียนไปยังแคชระยะไกล คุณอาจต้องการให้เฉพาะระบบ CI เท่านั้นที่เขียนไปยังแคชระยะไกลได้
ใช้ Flag ต่อไปนี้เพื่ออ่านและเขียนไปยังแคชระยะไกล
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 Sockets
แคช HTTP ระยะไกลรองรับการเชื่อมต่อผ่าน Unix Domain Socket ลักษณะการทำงาน
จะคล้ายกับแฟล็ก --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 ต้องสร้างสถานะใหม่ก่อนใช้แคชระยะไกล
ลิงก์ภายนอก
การสร้างในศูนย์ข้อมูล: ทีม Bazel ได้พูดเรื่องการแคชและการดำเนินการระยะไกลที่ FOSDEM 2018
บิลด์ Bazel ที่เร็วขึ้นด้วยการแคชระยะไกล: การเปรียบเทียบ: Nicolò Valigi เขียนบล็อกโพสต์ ซึ่งเขาเปรียบเทียบการแคชระยะไกลใน Bazel