创建永久性工作器

报告问题 查看来源 每晚 · 7.2。 · 7.1敬上 · 7.0 · 6.5 · 6.4

永久性工作器可让您的构建更快。如果 您的 build 中存在具有较高启动成本或 从交叉操作缓存中受益,您可能需要自行实现 来执行这些操作。

Bazel 服务器使用 stdin/stdout 与工作器进行通信。它 支持使用协议缓冲区或 JSON 字符串。

worker 实现包含两个部分:

使 worker

持久性工作器需要满足以下几项要求:

  • 上面写着: WorkRequests 从其 stdin 开始。
  • 它会编写 WorkResponses (且只有 WorkResponse)映射到其 stdout
  • 它接受 --persistent_worker 标志。封装容器必须识别 --persistent_worker 命令行 flag,并且仅在满足以下条件时才会使自身持久保留: 否则必须进行单样本编译并退出。

如果您的程序遵守这些要求,则可将其用作 员工!

工作请求

WorkRequest 包含 worker 的参数列表、 路径-摘要对,表示 worker 可以访问的输入(这不是 但您可以使用此信息进行缓存)和请求 ID(即 0) 单一请求模式

注意:虽然协议缓冲区规范使用“蛇形命名法”(request_id), JSON 协议采用“驼峰式大小写”(requestId).本文档采用驼峰命名法 但在谈论该字段时采用蛇形命名法,而不考虑 协议。

{
  "arguments" : ["--some_argument"],
  "inputs" : [
    { "path": "/path/to/my/file/1", "digest": "fdk3e2ml23d"},
    { "path": "/path/to/my/file/2", "digest": "1fwqd4qdd" }
 ],
  "requestId" : 12
}

可选的 verbosity 字段可用于请求额外的调试输出 。输出什么以及如何输出完全由 worker 决定。较高 值表示更详细的输出。将 --worker_verbose 标志传递给 Bazel 将 verbosity 字段设置为 10,但可以使用更小或更大的值 手动调整为不同的输出量。

可选的 sandbox_dir 字段仅供支持 多重沙盒

工作响应

WorkResponse 包含一个请求 ID、一个零或非零退出代码,以及一个 描述在处理或执行过程中遇到的任何错误的输出字符串 请求。output 字段包含简短说明;完整日志 写入 worker 的 stderr。由于工作器只能写入 WorkResponsesstdout,则 worker 通常会重定向 stdout stderr

{
  "exitCode" : 1,
  "output" : "Action failed with the following message:\nCould not find input
    file \"/path/to/my/file/1\"",
  "requestId" : 12
}

根据 protobuf 的标准,所有字段都是可选的。不过,Bazel 需要 WorkRequest 和相应的 WorkResponse,让它们具有相同的请求 id,因此如果请求 ID 为非零值,则必须指定请求 ID。这是一个有效的 WorkResponse

{
  "requestId" : 12,
}

request_id 为 0 表示“单工”请求,用于 不能与其他请求并行处理。服务器可保证 给定工作器接收只有 request_id 0 或只有 0 的请求 request_id 大于零。单工请求会按顺序发送, 例如,如果服务器在收到 (取消请求除外,请参阅下文)。

备注

  • 每个协议缓冲区均以 varint 格式的长度开头(请参阅 MessageLite.writeDelimitedTo()
  • JSON 请求和响应的前面没有大小指示符。
  • JSON 请求遵循与 protobuf 相同的结构,但使用标准格式, JSON 格式,并对所有字段名称使用驼峰式大小写。
  • 为了保持相同的向后和向前兼容性属性 与 protobuf 一样,JSON 工作器必须容忍这些消息中的未知字段, 对缺失值使用 protobuf 默认值。
  • Bazel 将请求存储为 protobuf,并使用 protobuf 的 JSON 格式

取消

Worker 可以选择允许在工作请求完成之前取消它们。 这特别适用于动态执行,因为本地 较快的远程执行可能经常会中断执行。要允许 取消,请将 supports-worker-cancellation: 1 添加到 execution-requirements 字段(见下文),并将 --experimental_worker_cancellation 标志。

取消请求是指WorkRequest设置了cancel字段(并且 同样,取消响应是包含 was_cancelledWorkResponse 字段集)。取消请求中必须包含的唯一其他字段 响应为 request_id,指示要取消哪个请求。request_id 对于单工工作器,字段将为 0;对于之前的作业,request_id 为非 0 为多路复用工作器发送了 WorkRequest。服务器可能会发送取消请求 对于工作器已响应的请求,在这种情况下,取消 请求。

无论如何,对于每条非取消WorkRequest消息,您都必须只回答一次, 而不是被取消了服务器发送取消请求后, 使用包含 request_id 集和 was_cancelledWorkResponse 进行响应 字段设为 true。系统也可以发送常规 WorkResponse,但 将忽略 outputexit_code 字段。

一旦发送针对 WorkRequest 的响应,Worker 就不得轻触 文件放在其工作目录中。服务器可以随意清理文件 包括临时文件。

制定使用工作器的规则

您还需要创建规则,生成由 worker。创建使用 worker 的 Starlark 规则就像 创建任何其他规则

此外,该规则需要包含对 worker 本身的引用,以及 需要满足一些要求。

提及 worker

使用工作器的规则需要包含一个引用工作器的字段 因此您需要创建一个 \*\_binary 规则实例来定义 。如果您的工作器名为 MyWorker.Java,那么这可能是 关联的规则:

java_binary(
    name = "worker",
    srcs = ["MyWorker.Java"],
)

这会创建“工作器”标签,表示工作器二进制文件。然后, 定义一条使用 worker 的规则。此规则应定义一个 是指工作器二进制文件。

如果您构建的工作器二进制文件位于名为“work”的软件包中,该软件包位于顶部 构建级别,则可能是属性定义:

"worker": attr.label(
    default = Label("//work:worker"),
    executable = True,
    cfg = "exec",
)

cfg = "exec" 表示应将 worker 构建为在您的 而不是在目标平台上运行(也就是说,使用 worker 用作工具)。

工作操作要求

使用工作器的规则创建了工作器要执行的操作。这些 都需满足几项要求

  • "arguments" 字段。此函数获取一个字符串列表,除最后一个 它们是在启动时传递给 worker 的参数。元素中的 “参数”list 是一个 flag-file(@ 前缀)参数。读取的工作器数 指定标志文件中的参数。您的 规则可以将工作器的非启动参数写入此标志文件。

  • "Execution-requirements" 字段,该字段采用包含以下内容的字典 "supports-workers" : "1" 和/或 "supports-multiplex-workers" : "1"

    “参数”和“Execution-requirements”都需要 操作数。此外,应由 JSON 工作器需要将 "requires-worker-protocol" : "json" 包含在 执行要求字段。"requires-worker-protocol" : "proto"也是 有效的执行要求,但 proto 工作器不需要, 因为它们是默认设置

    您还可以在执行要求中设置 worker-key-mnemonic。这个 如果您要将可执行文件重复用于多种操作类型 区分此工作器执行的操作。

  • 操作过程中生成的临时文件应保存到 worker 的目录。这会启用沙盒。

假设规则定义包含“worker”属性,除了 更改为“srcs”属性,即“output”属性 “args”属性,用于表示工作器 boot args 时,对 ctx.actions.run 的调用可能是:

ctx.actions.run(
  inputs=ctx.files.srcs,
  outputs=[ctx.outputs.output],
  executable=ctx.executable.worker,
  mnemonic="someMnemonic",
  execution_requirements={
    "supports-workers" : "1",
    "requires-worker-protocol" : "json"},
  arguments=ctx.attr.args + ["@flagfile"]
 )

如需查看其他示例,请参阅 实现永久性工作器

示例

Bazel 代码库使用 Java 编译器工作器 除了 示例 JSON 工作器 集成测试中使用的资源

您可以使用 基架 通过传入正确的回调将任何基于 Java 的工具添加到 Worker 中。

有关使用工作器的规则示例,请查看 Bazel 的 工作器集成测试

外部贡献者以多种语言协助员工开展工作;去 看看 Bazel 永久性工作器的 Polyglot 实现。 您可以 在 GitHub 上找到更多示例