หน้านี้จะพูดถึงการแคชระยะไกล การตั้งค่าเซิร์ฟเวอร์เพื่อโฮสต์แคช และการเรียกใช้บิลด์โดยใช้แคชระยะไกล
ทีมนักพัฒนาแอปและ/หรือระบบการรวมอย่างต่อเนื่อง (CI) ใช้แคชระยะไกลเพื่อแชร์เอาต์พุตของบิลด์ หากบิลด์ของคุณทำซ้ำได้ เอาต์พุตจากอุปกรณ์เครื่องหนึ่งจะนำมาใช้ซ้ำอีกเครื่องหนึ่งได้อย่างปลอดภัย ซึ่งอาจทำให้บิลด์เร็วขึ้นอย่างมาก
ภาพรวม
Bazel แยกบิลด์ออกเป็นขั้นตอนย่อยๆ ซึ่งเรียกว่า "การกระทำ" โดยแต่ละการดำเนินการจะมีอินพุต ชื่อเอาต์พุต บรรทัดคำสั่ง และตัวแปรสภาพแวดล้อม ระบบจะประกาศอินพุตที่จําเป็นและเอาต์พุตที่คาดหวังไว้อย่างชัดเจนสําหรับการดําเนินการแต่ละรายการ
คุณตั้งค่าเซิร์ฟเวอร์เป็นแคชระยะไกลสำหรับเอาต์พุตบิลด์ได้ ซึ่งก็คือเอาต์พุตการดำเนินการเหล่านี้ เอาต์พุตเหล่านี้ประกอบด้วยรายการชื่อไฟล์เอาต์พุตและแฮชของเนื้อหา แคชระยะไกลช่วยให้คุณนำเอาต์พุตของบิลด์จากบิลด์ของผู้ใช้รายอื่นมาใช้ใหม่แทนการสร้างเอาต์พุตใหม่แต่ละรายการในเครื่องได้
วิธีใช้การแคชจากระยะไกล
- ตั้งค่าเซิร์ฟเวอร์เป็นแบ็กเอนด์ของแคช
- กำหนดค่าบิลด์ Bazel เพื่อใช้แคชระยะไกล
- ใช้ Bazel เวอร์ชัน 0.10.0 ขึ้นไป
แคชระยะไกลจะจัดเก็บข้อมูล 2 ประเภทดังนี้
- แคชการดำเนินการซึ่งเป็นแมปของแฮชการดำเนินการกับข้อมูลเมตาของผลลัพธ์การดำเนินการ
- แหล่งเก็บข้อมูลที่ระบุเนื้อหาได้ (CAS) ของไฟล์เอาต์พุต
โปรดทราบว่าแคชระยะไกลจะจัดเก็บ Stdout และ stderr ไว้เพิ่มเติมสำหรับทุกๆ การดำเนินการ ดังนั้นการตรวจสอบ stdout/stderr ของ 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 เป็นแคชบิลด์ระยะไกลแบบโอเพนซอร์สที่คุณสามารถใช้ในโครงสร้างพื้นฐานได้ และประสบความสำเร็จในการนำไปใช้ในเวอร์ชันที่ใช้งานจริง ในหลายๆ บริษัทตั้งแต่ต้นปี 2018 โปรดทราบว่าโปรเจ็กต์ Bazel ไม่มีบริการสนับสนุนด้านเทคนิคสำหรับรีโมตแบบเบเซล
แคชนี้จะจัดเก็บเนื้อหาไว้ในดิสก์และมีการรวบรวมการ์เบจเพื่อบังคับใช้ขีดจำกัดพื้นที่เก็บข้อมูลสูงสุดและล้างอาร์ติแฟกต์ที่ไม่ได้ใช้ แคชมีพร้อมใช้งานในรูปแบบ [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 โดยเพิ่มแฟล็กต่อไปนี้ลงในคำสั่ง 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
- ส่ง 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 เพื่อดาวน์โหลดข้อมูลเมตาของผลการดำเนินการสำหรับการดำเนินการที่มีแฮช 01ba4719...
ของ SHA256 จะมีลักษณะดังนี้
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-cache
เช่น
java_library(
name = "target",
tags = ["no-cache"],
)
ลบเนื้อหาออกจากแคชระยะไกล
การลบเนื้อหาจากแคชระยะไกลเป็นส่วนหนึ่งของการจัดการเซิร์ฟเวอร์ของคุณ วิธีลบเนื้อหาออกจากแคชระยะไกลจะขึ้นอยู่กับเซิร์ฟเวอร์ที่คุณตั้งค่าไว้เป็นแคช เมื่อลบเอาต์พุต ให้ลบแคชทั้งหมดหรือลบเอาต์พุตเก่า
ระบบจะจัดเก็บเอาต์พุตที่แคชไว้เป็นชุดชื่อและแฮช เมื่อลบเนื้อหา คุณจะไม่สามารถแยกได้ว่าเอาต์พุตใดเป็นของบิลด์ที่เฉพาะเจาะจง
คุณอาจต้องลบเนื้อหาออกจากแคชเพื่อดําเนินการต่อไปนี้
- สร้างแคชที่สะอาดหลังจากแคชถูกทำลาย
- ลดปริมาณพื้นที่เก็บข้อมูลที่ใช้โดยการลบเอาต์พุตเก่า
ซ็อกเก็ต Unix
แคช HTTP ระยะไกลรองรับการเชื่อมต่อผ่านซ็อกเก็ตโดเมน Unix ลักษณะการทำงานจะคล้ายกับ Flag --unix-socket
ของ Curl ใช้รายการต่อไปนี้เพื่อกำหนดค่าซ็อกเก็ตโดเมน Uniix
build --remote_cache=http://your.host:port
build --remote_cache_proxy=unix:/path/to/socket
ฟีเจอร์นี้ไม่รองรับใน Windows
ดิสก์แคช
Bazel สามารถใช้ไดเรกทอรีในระบบไฟล์เป็นแคชระยะไกล ซึ่งมีประโยชน์ในการแชร์อาร์ติแฟกต์ของบิลด์เมื่อเปลี่ยนสาขาและ/หรือทำงานบนพื้นที่ทำงานหลายแห่งในโปรเจ็กต์เดียวกัน เช่น การชำระเงินหลายรายการ เนื่องจากBazel ไม่ได้รวบรวมไดเรกทอรีแบบขยะ คุณอาจต้องทำให้การล้างข้อมูลไดเรกทอรีนี้ทำงานเป็นช่วงๆ โดยอัตโนมัติ เปิดใช้งานดิสก์แคชโดยทำดังนี้
build --disk_cache=path/to/build/cache
คุณส่งเส้นทางที่เจาะจงผู้ใช้ไปยังแฟล็ก --disk_cache
โดยใช้ชื่อแทน ~
ได้
(Bazel จะแทนที่ไดเรกทอรีหน้าแรกของผู้ใช้ปัจจุบัน) วิธีนี้มีประโยชน์เมื่อเปิดแคชดิสก์ให้กับนักพัฒนาซอฟต์แวร์ทุกรายของโครงการผ่านไฟล์ของ .bazelrc
ที่ตรวจสอบแล้วของโปรเจ็กต์
ปัญหาที่ทราบ
การแก้ไขไฟล์อินพุตระหว่างบิลด์
เมื่อมีการแก้ไขไฟล์อินพุตระหว่างบิลด์ Bazel อาจอัปโหลดผลลัพธ์ที่ไม่ถูกต้องไปยังแคชระยะไกล คุณเปิดใช้การตรวจจับการเปลี่ยนแปลงได้ด้วยแฟล็ก --experimental_guard_against_concurrent_changes
ไม่มีปัญหาที่รู้จักและจะเปิดใช้โดยค่าเริ่มต้นในรุ่นถัดไป
ดูข้อมูลอัปเดตใน [ปัญหา #3360] โดยทั่วไป ให้หลีกเลี่ยงการแก้ไขไฟล์ต้นฉบับระหว่างการสร้าง
ตัวแปรสภาพแวดล้อมรั่วไหลไปสู่การดําเนินการ
การกำหนดการดำเนินการมีตัวแปรสภาพแวดล้อม นี่อาจเป็นปัญหาสำหรับ
การแชร์ Hit แคชระยะไกลระหว่างเครื่อง ตัวอย่างเช่น สภาพแวดล้อมที่มีตัวแปร $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 ต้องสร้างบิลด์อีกครั้งก่อนใช้แคชระยะไกล
ลิงก์ภายนอก
งานบิลด์ของคุณในศูนย์ข้อมูล: ทีม Bazel ให้พูดคุยเกี่ยวกับการแคชและดำเนินการจากระยะไกลในงาน FOSDEM 2018
สร้างแอปที่รวดเร็วยิ่งขึ้นด้วยการแคชจากระยะไกล: Nicolò Valigi เขียนบล็อกโพสต์ ที่ใช้เปรียบเทียบการแคชจากระยะไกลใน Bazel