Trang này mô tả trình thực thi multiplex, cách viết quy tắc tương thích với multiplex và cách giải quyết một số giới hạn nhất định.
Trình thực thi Multiplex cho phép Bazel xử lý nhiều yêu cầu bằng một quy trình trình thực thi duy nhất. Đối với các trình thực thi đa luồng, Bazel có thể sử dụng ít tài nguyên hơn để đạt được hiệu suất tương đương hoặc tốt hơn. Ví dụ: thay vì có một quy trình cho mỗi trình thực thi, Bazel có thể có 4 trình thực thi ghép kênh trò chuyện với cùng một quy trình của trình thực thi, sau đó có thể xử lý song song các yêu cầu. Đối với các ngôn ngữ như Java và Scala, cách này giúp tiết kiệm thời gian khởi động JVM và thời gian biên dịch JIT, nói chung là cho phép sử dụng một bộ nhớ đệm dùng chung giữa tất cả các worker cùng loại.
Tổng quan
Có hai lớp giữa máy chủ Bazel và quy trình worker. Đối với một số lệnh ghi nhớ có thể chạy song song các quy trình, Bazel sẽ nhận được WorkerProxy
từ nhóm worker. WorkerProxy
chuyển tiếp các yêu cầu đến quy trình trình thực thi
theo tuần tự cùng với request_id
, quy trình này sẽ xử lý yêu cầu
và gửi phản hồi cho WorkerMultiplexer
. Khi nhận được phản hồi, WorkerMultiplexer
sẽ phân tích cú pháp request_id
, sau đó chuyển tiếp các phản hồi này trở lại đúng WorkerProxy
. Cũng giống như với worker không được ghép kênh, mọi hoạt động giao tiếp đều được thực hiện qua quy trình nhập/xuất tiêu chuẩn, nhưng công cụ này không thể chỉ sử dụng stderr
cho đầu ra hiển thị cho người dùng (xem bên dưới).
Mỗi worker có một khoá. Bazel sử dụng mã băm của khoá (bao gồm các biến môi trường, gốc thực thi và bộ nhớ ghi nhớ) để xác định cần sử dụng WorkerMultiplexer
nào. Các WorkerProxy
giao tiếp với cùng một WorkerMultiplexer
nếu chúng có cùng một mã băm. Do đó, giả sử các biến môi trường và gốc thực thi là giống nhau trong một lệnh gọi Bazel, thì mỗi ký tự ghi nhớ duy nhất chỉ có thể có một WorkerMultiplexer
và một quy trình trình thực thi. Tổng số trình thực thi (bao gồm cả trình thực thi thông thường và WorkerProxy
) vẫn bị giới hạn trong --worker_max_instances
.
Viết quy tắc tương thích với multiplex
Quy trình trình thực thi của quy tắc phải đa luồng để tận dụng các trình thực thi Multiplex. Protobuf cho phép một bộ quy tắc phân tích cú pháp một yêu cầu ngay cả khi có thể có nhiều yêu cầu chồng chéo trong luồng. Bất cứ khi nào quy trình worker phân tích cú pháp yêu cầu từ luồng, nó sẽ xử lý yêu cầu trong một luồng mới. Vì nhiều luồng có thể hoàn tất và ghi vào luồng cùng một lúc, nên quy trình thực thi cần đảm bảo các phản hồi được viết tỉ mỉ (các thông báo không chồng chéo nhau). Phản hồi phải chứa request_id
của yêu cầu mà chúng đang xử lý.
Xử lý đầu ra multiplex
Trình thực thi Multiplex cần cẩn thận hơn khi xử lý đầu ra so với trình thực thi Multiplex. Mọi nội dung được gửi đến stderr
sẽ chuyển vào một tệp nhật ký duy nhất được chia sẻ giữa tất cả WorkerProxy
cùng loại, được xen kẽ ngẫu nhiên giữa các yêu cầu đồng thời. Bạn nên chuyển hướng stdout
vào stderr
, nhưng đừng thu thập kết quả đó vào trường output
của WorkResponse
, vì điều này có thể cho thấy các phần đầu ra bị hỏng.
Nếu công cụ của bạn chỉ gửi đầu ra dành cho người dùng đến stdout
hoặc stderr
, bạn cần thay đổi hành vi đó trước khi có thể bật multiplex worker.
Bật multiplex worker
Trình thực thi Multiplex không được bật theo mặc định. Một bộ quy tắc có thể bật trình thực thi multiplex bằng cách sử dụng thẻ supports-multiplex-workers
trong execution_requirements
của một hành động (tương tự như thẻ supports-workers
cho phép các trình thực thi thông thường). Tương tự như khi sử dụng trình thực thi thông thường, bạn cần chỉ định chiến lược trình thực thi ở cấp bộ quy tắc (ví dụ: --strategy=[some_mnemonic]=worker
) hoặc thường ở cấp chiến lược (ví dụ: --dynamic_local_strategy=worker,standalone
). Không cần gắn cờ bổ sung nào và supports-multiplex-workers
sẽ được ưu tiên hơn supports-workers
nếu bạn đặt cả hai. Bạn có thể tắt multiplex worker trên toàn cầu bằng cách truyền --noworker_multiplex
.
Bạn nên sử dụng multiplex worker nếu có thể, để giảm áp lực bộ nhớ và cải thiện hiệu suất. Tuy nhiên, multiplex worker hiện không tương thích với quá trình thực thi động trừ phi triển khai hộp cát multiplex. Việc cố gắng chạy các trình thực thi multiplex không có hộp cát bằng chế độ thực thi động sẽ tự động sử dụng các trình thực thi singleplex có hộp cát.
Hộp cát Multiplex
Trình thực thi Multiplex có thể được tạo hộp cát bằng cách thêm tuỳ chọn hỗ trợ rõ ràng cho lớp đó trong quá trình triển khai trình thực thi. Mặc dù bạn có thể thực hiện hộp cát của trình thực thi singleplex bằng cách chạy từng quy trình của trình thực thi trong hộp cát riêng, nhưng các trình thực thi multiplex lại chia sẻ thư mục đang làm việc của quy trình giữa nhiều yêu cầu song song. Để cho phép hộp cát của các worker, worker phải hỗ trợ đọc và ghi vào một thư mục con được chỉ định trong mỗi yêu cầu, thay vì trực tiếp trong thư mục đang hoạt động của nó.
Để hỗ trợ hộp cát multiplex, worker phải sử dụng trường sandbox_dir
từ WorkRequest
và dùng trường đó làm tiền tố cho tất cả lượt đọc và ghi tệp.
Mặc dù các trường arguments
và inputs
vẫn không thay đổi so với yêu cầu không có hộp cát, nhưng dữ liệu đầu vào thực tế sẽ có liên quan đến sandbox_dir
. Trình thực thi phải dịch các đường dẫn tệp có trong arguments
và inputs
để đọc từ đường dẫn đã sửa đổi này, đồng thời phải ghi tất cả kết quả đầu ra liên quan đến sandbox_dir
.
Điều này bao gồm các đường dẫn như ".", cũng như các đường dẫn tìm thấy trong các tệp được chỉ định trong đối số (chẳng hạn như các đối số "argfile").
Sau khi một trình thực thi hỗ trợ hộp cát multiplex, tập hợp quy tắc có thể khai báo tính năng hỗ trợ này bằng cách thêm supports-multiplex-sandboxing
vào execution_requirements
của một hành động. Sau đó, Bazel sẽ sử dụng hộp cát Multiplex nếu cờ --experimental_worker_multiplex_sandboxing
được truyền hoặc nếu worker này được dùng với chế độ thực thi động.
Tệp trình chạy của một trình thực thi multiplex có hộp cát vẫn tương ứng với thư mục làm việc của quy trình trình thực thi này. Do đó, nếu một tệp được dùng cho cả hai mục đích chạy trình thực thi và dữ liệu đầu vào, thì bạn phải chỉ định tệp đó làm dữ liệu đầu vào trong đối số tệp cờ cũng như trong tools
, executable
hoặc runfiles
.