多重工作器(实验性功能)

报告问题 查看源代码 每夜 build · 7.4 . 7.3 · 7.2 · 7.1敬上 · 7.0敬上 · 6.5

本页介绍了多路复用工作器、如何编写与多路复用兼容的规则,以及针对某些限制的权宜解决方法。

多重工作器允许 Bazel 使用单个工作器处理多个请求 过程。对于多线程工作器,Bazel 可以使用更少的资源 达到相同或更好的效果。例如,Bazel 可以有四个多路复用工作器与同一个工作器进程通信,而不是每个工作器都有一个工作器进程,然后该进程可以并行处理请求。对于 例如 Java 和 Scala,这可以节省 JVM 预热时间和 JIT 编译 它通常允许在所有工作器之间使用一个共享缓存 同一类型。

概览

Bazel 服务器和工作器进程之间有两个层。对于特定 可以并行运行进程的助记符,Bazel 会从WorkerProxy 或工作器池。WorkerProxy 会将请求连同 request_id 依次转发给 worker 进程,worker 进程会处理请求并将响应发送给 WorkerMultiplexer。当 WorkerMultiplexer 收到响应后,它会解析 request_id,然后转发响应 返回正确的 WorkerProxy。与非多路复用工作器一样, 通过标准的输入/输出进行通信,但该工具不能只使用 stderr,用于用户可见的输出(请参阅下文)。

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

编写与多路复用兼容的规则

规则的工作器进程应该是多线程的,以便利用 多路复用工作器。Protobuf 允许规则集解析单个请求,甚至 但数据流中可能会堆积多个请求每当 工作器进程解析来自数据流的请求,它应该在 新会话串。因为不同的线程可以在 同时,工作器进程需要确保将响应写入 原子方式(消息不重叠)。响应必须包含 request_id 表示正在处理的请求。

处理多路复用输出

与单工序工作器相比,多工序工作器在处理输出时需要更加小心。发送到 stderr 的所有内容都将进入一个日志文件,该日志文件由所有同类型的 WorkerProxy 共享,并在并发请求之间随机交错。重定向 stdout 时 建议存储到 stderr 中,请勿将该输出收集到 output WorkResponse 字段中的值,因为这可能会显示用户损坏的输出片段。 如果您的工具仅将面向用户的输出发送到 stdoutstderr,您将需要 您需要先更改该行为,然后才能启用 Multix Worker。

启用多路复用工作器

多路复用工作器默认处于停用状态。规则集可以通过在操作的 execution_requirements 中使用 supports-multiplex-workers 标记来启用多路复用工作器(就像 supports-workers 标记启用常规工作器一样)。与使用常规工作器一样,您需要在规则集级别(例如 --strategy=[some_mnemonic]=worker)或通常在策略级别(例如 --dynamic_local_strategy=worker,standalone)指定工作器策略。无需其他标志,如果同时设置了 supports-multiplex-workerssupports-workers,则 supports-multiplex-workers 优先于 supports-workers。您可以关闭多路复用工作器 通过传递 --noworker_multiplex 在全局范围内。

建议规则集尽可能使用多路复用工作器,以减少内存 并提升性能。不过,Multix worker 目前 与动态执行功能兼容,除非它们 实现多路复用沙盒尝试使用动态执行运行非沙盒化多工序工作器时,系统会改为静默使用沙盒化单工序工作器。

多重沙盒

通过在工作器实现中添加对多路复用工作器的明确支持,可以将多路复用工作器沙盒化。虽然单工序工作器沙盒化可以通过在各自的沙盒中运行每个工作器进程来实现,但多工序工作器会在多个并行请求之间共享进程工作目录。为了允许对多工工作器进行沙盒化处理,工作器必须支持从每个请求中指定的子目录读取和写入,而不是直接在其工作目录中读取和写入。

如需支持多重沙盒,工作器必须使用 sandbox_dir 字段 并从 WorkRequest 中将其用作所有文件读写的前缀。 虽然 argumentsinputs 字段与未沙盒化请求保持不变,但实际输入相对于 sandbox_dir。工作器必须 翻译在 argumentsinputs 中找到的文件路径,以便从中读取数据 修改了路径,并且还必须写入相对于 sandbox_dir 的所有输出。 其中包括“.”等路径,以及指定文件中的路径 (例如 "argfile" 参数)。

当 worker 支持多重沙盒化后,规则集可以通过向操作的 execution_requirements 添加 supports-multiplex-sandboxing 来声明此支持。然后,Bazel 将使用多重沙盒 如果传递了 --experimental_worker_multiplex_sandboxing 标志,或者 工作器用于动态执行。

沙盒化多重 Worker 的 Worker 文件仍然是相对于 工作器进程的工作目录。因此,如果一个文件 同时用于运行 worker 和用作输入,则必须同时将其指定为 标志文件参数以及 toolsexecutablerunfiles