多路复用工作器(实验性功能)

本页面介绍多路复用工作器,如何编写兼容多路复用的规则,以及特定限制的解决方法。

多路工作器可让 Bazel 通过单个工作器进程处理多个请求。对于多线程工作器,Bazel 可以使用更少的资源来实现相同或更好的性能。例如,Bazel 可以使每个多路复用工作器与同一工作器进程通信,然后该工作器可以并行处理请求,而不是每个工作器使用一个工作器进程。对于 Java 和 Scala 等语言,这样可以节省 JVM 预热时间和 JIT 编译时间,并且一般而言,它允许在相同类型的所有工作器之间共享一个共享缓存。

概览

Bazel 服务器与工作器进程之间有两个层。对于某些可以并行运行进程的助记符,Bazel 会从工作器池获取 WorkerProxyWorkerProxy 将请求与 request_id 依序转发到工作器进程,工作器进程会处理该请求并将响应发送到 WorkerMultiplexer。当 WorkerMultiplexer 收到响应时,它会解析 request_id,然后将响应转发回正确的 WorkerProxy。与非多路复用工作器一样,所有通信都通过标准输入/输出进行,但该工具不能只将 stderr 用于用户可见的输出(参见下文)。中披露政府所要求信息的数量和类型。

每个工作器都有一个键。Bazel 会使用该密钥的哈希代码(由环境变量、执行根和助记符组成)来确定要使用的 WorkerMultiplexer。如果 WorkerProxy 具有相同的哈希代码,它们就会与同一 WorkerMultiplexer 进行通信。因此,假设单次 Bazel 调用中的环境变量和执行根相同,每个唯一助记符只能有一个 WorkerMultiplexer 和一个工作器进程。工作器总数(包括常规工作器和 WorkerProxy)仍受 --worker_max_instances 的限制。

编写兼容多路复用的规则

该规则的工作器进程应该是多线程的进程,以便充分利用多路复用工作器。Protobuf 允许规则集解析单个请求,即使可能有多个请求在数据流中堆积起来也是如此。每当工作器进程解析来自数据流的请求时,它都应在新线程中处理请求。由于不同的线程可以同时完成和写入流,因此工作器进程需要确保以原子方式写入响应(消息不会重叠)。响应必须包含所正在处理的请求的 request_id

处理多路复用输出

与多路复用工作器相比,多路复用工作器需要谨慎处理输出。发送到 stderr 的任何内容都将进入单个同一类型的所有 WorkerProxy 之间共享的日志文件,并在并发请求之间随机交错。建议您将 stdout 重定向到 stderr,但不要将该输出收集到 WorkResponseoutput 字段中,因为这可能会显示用户重组的输出片段 如果您的工具仅将面向用户的输出发送到 stdoutstderr,您需要先更改该行为,然后才能启用多路复用工作器。

启用多路复用工作器

默认情况下,多路复用工作器处于停用状态。规则集可以通过在操作的 execution_requirements 中使用 supports-multiplex-workers 标记来启用多路复用工作器(就像 supports-workers 标记支持常规工作器一样)。与使用常规工作器时一样,您需要在规则集级别(例如 --strategy=[some_mnemonic]=worker)或通常在策略级别(例如--dynamic_local_strategy=worker,standalone)。无需额外的标志,supports-multiplex-workers 优先于 supports-workers(如果这两者已设置)。您可以通过传递 --noexperimental_worker_multiplex 全局关闭多路复用工作器。

如果可能,建议使用规则集工作器,以减少内存压力并提高性能。不过,除非实现了多路复用沙盒,否则多路复用工作器与动态执行不兼容。尝试动态执行非沙盒多路复用工作器时,系统将静默地使用在沙盒中运行的单工工作器。

多路复用沙盒

通过在工作器实现中明确支持多路复用工作器,可以对其进行沙盒化。虽然单工工作器工作器沙盒可以在其自己的沙盒中运行各个工作器进程,但多路复用工作器会在多个并行请求之间共享进程工作目录。要允许对多路工作器进行沙盒化,工作器必须支持从每个请求中指定的子目录(而不是直接在其工作目录中)中读取数据以及向其中写入数据。

如需支持多路复用沙盒,工作器必须使用 WorkRequest 中的 sandbox_dir 字段,并将该字段用作所有文件读取和写入的前缀。虽然未经过沙盒处理的请求中 argumentsinputs 字段保持不变,但实际输入是相对于 sandbox_dir 的。工作器必须转换 argumentsinputs 中的文件路径才能读取此修改后的路径,还必须写入相对于 sandbox_dir 的所有输出。这包括“.”等路径,以及在参数中指定的文件(例如 "argfile" 参数)中找到的路径。

工作器支持多路复用沙盒后,规则集可以通过将 supports-multiplex-sandboxing 添加到操作的 execution_requirements 中来声明此支持。如果传递了 --experimental_worker_multiplex_sandboxing 标志,或者工作器与动态执行功能配合使用,Bazel 将采用多路复用沙盒。

沙盒化多路复用工作器的工作文件仍相对于工作器进程的工作目录相关。因此,如果某个文件同时用于运行工作器和作为输入,则必须在 flagfile 参数中指定为输入,并在 toolsexecutablerunfiles