跳至主要内容
非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

分布式任务执行 (DTE)

Lerna 通过缓存功能--since 标志提升平均 CI 效率。但当核心代码变更导致所有任务都需要运行时,只有增加代理任务和高效并行化才能真正优化性能。

最常见的并行化策略是按类型分桶:测试任务集中在一个任务、构建任务在另一个、lint 检查在第三个。这种策略称为分桶执行。虽然某些测试任务依赖构建产物会增加复杂度,但合理处理后典型流程如下图所示:测试任务等待构建就绪,而构建和 lint 任务可立即启动。

使用分桶策略的CI流程

分桶策略的痛点是部分任务会出现空闲等待。Nx 的分布式任务执行通过基于任务平均耗时动态分配任务,将空闲时间压缩至最低。同时确保任务顺序正确,并通过分布式缓存使构建产物在所有需要它的代理任务上可用。

启用 Nx 分布式任务执行后,任务流程图将变为:

使用DTE的CI流程

不仅 CI 耗时大幅缩短,调试体验也与单任务执行完全一致——Nx 通过分布式缓存在主任务上完整复现所有日志和构建产物。

详见优化极端CI场景的完整指南

配置流程

要实现分布式任务执行,您需要:(1) 连接至Nx Cloud;(2) 在CI工作流中启用DTE。

1. Connect to Nx Cloud via the interactive, browser-based workflow
npx nx connect-to-nx-cloud

配置您的CI工作流

不同组织的CI/CD流水线管理方式各异,因此无法涵盖所有场景。但以下主流CI平台中为Nx CLI配置DTE的示例可作为理想起点,这些配置能轻松适配Lerna特有命令(如lerna run,而非nx run-manynx affected):

注意:仅支持缓存的操作可分布式执行,因其需在主控任务上重放。

关于DTE配置的完整指南,请参阅此文档

CI 执行流程

分布式任务执行适用于所有 CI 平台。您负责启动 CI 任务,Nx Cloud 协调任务协作。需创建两类任务:

  1. 主控任务:决策执行逻辑

  2. 代理任务:实际执行操作

主控任务流程:

# Coordinate the agents to run the tasks
- npx nx-cloud start-ci-run
# Run any commands you want here
- lerna run lint --since=main & lerna run test --since=main & lerna run build --since=main
# Stop any run away agents
- npx nx-cloud stop-all-agents

代理任务执行流程非常简单:

# Wait for tasks to execute
- npx nx-cloud start-agent

主控任务配置与非分布式环境基本一致,只需在开头添加 npx nx-cloud start-ci-run,结尾可选添加 npx nx-cloud stop-all-agents

代理任务通过长期运行的 start-agent 进程执行与给定 CI 运行相关的所有任务。设置这些代理唯一需要做的就是调用 npx nx-cloud start-agent。该进程将持续运行直至 Nx Cloud 发出终止指令。

注意:主控任务与代理任务必须保持环境一致和代码同步。它们同时启动,主控任务结束时所有代理任务自动终止。

需特别注意:Nx Cloud代理并非机器实体,而是运行在机器上的长期进程。换言之,Nx Cloud不管理您的代理实例——您需要在CI配置中自行管理(参考前文CI示例)。

Nx Cloud 担任协调者角色:主控任务声明执行目标,Nx Cloud 将任务动态分配给代理,并在代理间自动传输文件。

最终效果:当主控任务完成 lerna run build --since=main 时,所有代理生成的产物文件会自动同步至主控任务,如同本地构建。

并行执行策略

--concurrency 参数将传递给代理。例如 npx lerna run build --since=main --concurrency=3 --dte 表示每个代理最多并行 3 个构建任务。若部署 10 个代理,则全系统最高并行 30 个构建任务。

应最大化并行命令数量:

- lerna run lint --since=main
- lerna run test --since=main
- lerna run build --since=main

不如

- lerna run lint --since=main & lerna run test --since=main & lerna run build --since=main

后者会同时调度所有三个命令,因此如果某个代理找不到需要构建的内容,就会开始运行测试和 lint 检查。这样不仅能提高代理的利用率,还能缩短 CI 时间。

参考资源