หน้านี้ครอบคลุมการแคชระยะไกล การตั้งค่าเซิร์ฟเวอร์เพื่อโฮสต์แคช และ การเรียกใช้บิลด์โดยใช้แคชระยะไกล
แคชระยะไกลใช้โดยทีมนักพัฒนาซอฟต์แวร์และ/หรือระบบการรวมอย่างต่อเนื่อง (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/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 รองรับทั้ง REST และ gRPC Remote Cache API
โปรดดูวิธีการใช้งานในหน้า GitHub
Google Cloud Storage
[Google Cloud Storage] คือที่เก็บข้อมูลออบเจ็กต์ที่มีการจัดการเต็มรูปแบบซึ่งมี HTTP API ที่เข้ากันได้กับโปรโตคอลการแคชระยะไกลของ Bazel โดยคุณต้องมีบัญชี Google Cloud ที่เปิดใช้การเรียกเก็บเงิน
หากต้องการใช้ Cloud Storage เป็นแคช ให้ทำดังนี้
สร้างที่เก็บข้อมูล ตรวจสอบว่าคุณเลือกตำแหน่ง Bucket ที่อยู่ใกล้คุณที่สุด เนื่องจากแบนด์วิดท์เครือข่าย มีความสำคัญต่อแคชระยะไกล
สร้างบัญชีบริการสำหรับ Bazel เพื่อตรวจสอบสิทธิ์กับ Cloud Storage ดูการสร้างบัญชีบริการ
สร้างคีย์ JSON ลับ แล้วส่งไปยัง Bazel เพื่อการตรวจสอบสิทธิ์ จัดเก็บคีย์อย่างปลอดภัย เนื่องจากทุกคนที่มีคีย์จะอ่านและเขียนข้อมูลใดก็ได้ ไปยัง/จาก Bucket ของ 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-cache เช่น
java_library(
name = "target",
tags = ["no-cache"],
)
ลบเนื้อหาออกจากแคชระยะไกล
การลบเนื้อหาออกจากแคชระยะไกลเป็นส่วนหนึ่งของการจัดการเซิร์ฟเวอร์ วิธีกำจัดเนื้อหาออกจากแคชระยะไกลจะขึ้นอยู่กับเซิร์ฟเวอร์ที่คุณตั้งค่าเป็นแคช เมื่อลบเอาต์พุต ให้ลบแคชทั้งหมด หรือลบเอาต์พุตเก่า
ระบบจะจัดเก็บเอาต์พุตที่แคชไว้เป็นชุดชื่อและแฮช เมื่อลบเนื้อหา จะไม่มีวิธีแยกแยะว่าเอาต์พุตใดเป็นของบิลด์ใด
คุณอาจต้องการลบเนื้อหาออกจากแคชเพื่อดำเนินการต่อไปนี้
- สร้างแคชที่สะอาดหลังจากแคชถูกวางยา
- ลดปริมาณพื้นที่เก็บข้อมูลที่ใช้โดยการลบเอาต์พุตเก่า
Unix Sockets
แคช HTTP ระยะไกลรองรับการเชื่อมต่อผ่าน Unix Domain Socket ลักษณะการทำงาน
จะคล้ายกับแฟล็ก --unix-socket ของ curl ใช้ข้อมูลต่อไปนี้เพื่อกำหนดค่าซ็อกเก็ตโดเมน unix
build --remote_cache=http://your.host:port
build --remote_cache_proxy=unix:/path/to/socketWindows ไม่รองรับฟีเจอร์นี้
แคชดิสก์
Bazel สามารถใช้ไดเรกทอรีในระบบไฟล์เป็นแคชระยะไกลได้ ซึ่งมีประโยชน์สำหรับการแชร์อาร์ติแฟกต์บิลด์เมื่อเปลี่ยนสาขาและ/หรือทำงานในพื้นที่ทำงานหลายแห่งของโปรเจ็กต์เดียวกัน เช่น การชำระเงินหลายครั้ง เนื่องจาก Bazel ไม่ได้ล้างข้อมูลในไดเรกทอรีโดยอัตโนมัติ คุณอาจต้องตั้งค่าให้ล้างข้อมูลในไดเรกทอรีนี้เป็นระยะๆ เปิดใช้แคชดิสก์ดังนี้
build --disk_cache=path/to/build/cacheคุณส่งเส้นทางที่เฉพาะเจาะจงของผู้ใช้ไปยังแฟล็ก --disk_cache ได้โดยใช้นามแฝง ~
(Bazel จะแทนที่ไดเรกทอรีหลักของผู้ใช้ปัจจุบัน) ซึ่งจะมีประโยชน์
เมื่อเปิดใช้แคชดิสก์สำหรับนักพัฒนาซอฟต์แวร์ทั้งหมดของโปรเจ็กต์ผ่านไฟล์ .bazelrc ที่เช็คอินของโปรเจ็กต์
ปัญหาที่ทราบ
การแก้ไขไฟล์อินพุตระหว่างบิลด์
เมื่อมีการแก้ไขไฟล์อินพุตระหว่างการสร้าง 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