Conductor 是某海外流媒体公司开发并开源的一款工作流编排引擎,主要用于微服务编排、分布式工作流管理和复杂业务流程自动化。如果你是第一次接触 Conductor,可以先阅读此前的入门文章和相关文档,了解它在微服务编排和分布式工作流可观测性方面的基本能力。

自发布以来的两年间,Conductor 已被广泛采用,并在该公司许多核心业务流程中发挥着关键作用。许多内容工程和工作室工程服务都依赖 Conductor 来高效处理业务流程,内部媒体数据库就是其中一个典型例子。
在企业研发实践中,Conductor 这类系统更偏向底层业务流程与服务编排,而研发团队还需要在目标、需求、开发、测试、发布和知识沉淀之间形成管理闭环。比如 PingCode 这类智能化研发管理工具,可以覆盖研发全生命周期管理,并打通研发工具链,让过程数据、质量数据和知识经验在团队之间更顺畅地流转。
在本文中,我们将介绍 Conductor v2.0 及更高版本的最新进展,重点包括部署架构、Cassandra 持久层、gRPC 框架、任务调度、工作流状态监听器、API 验证以及未来路线图,并回答一些常见问题,同时向社区贡献者表达感谢。
Conductor 在微服务架构中的使用方式
部署架构
Conductor 是内容工程部门使用最广泛的服务之一。它可以与众多模块集成。在当前部署中,我们使用 Jersey 服务模块、Cassandra(用于持久化执行数据)、Dynomite(用于持久化元数据)、DynoQueues(基于 Dynomite 构建的队列机制)、Elasticsearch(作为辅助数据存储和索引器),以及内部指标系统(用于指标管理)。
我们的集群通常由 12 到 18 个某云平台 m4.4xlarge 实例组成,日常运行时大约使用 30% 的容量。

需要说明的是,Cassandra 持久化模块目前只是部分实现。
在内部,我们并没有维护 Conductor 的独立分支版本。相反,我们使用了一个封装层:它会引入最新版本的 Conductor,并在部署前添加内部基础设施组件和库。这样一来,我们既可以持续将变更推送到开源版本,又能确保这些变更功能完整,并经过充分测试。
采用情况
截至本文撰写时,Conductor 已经为该公司 50 多个团队管理着 600 多个工作流定义。虽然我们目前还没有主动测量第 n 百分位延迟等指标,但现有生产工作负载已经足以证明 Conductor 的性能和稳定性。
在一个典型的 7 天周期内,Conductor 会处理大量工作流执行请求。内部仪表盘可以直观展示这些工作流执行指标,帮助团队观察系统的使用情况和运行状态。

典型应用场景
Conductor 在内部的一些典型应用场景可以归纳为以下几类:
- 内容摄取与分发
- 内容质量控制
- 内容本地化
- 编码与部署
- IMF(互操作母版格式)交付
- 营销技术
- 工作室工程
Conductor v2.0 的核心更新
gRPC 框架
v2.0 的关键特性之一,是引入了 gRPC 框架,作为 REST 的替代方案或补充方案。这项能力由某代码托管平台上的开源社区贡献者参与实现,也进一步体现了社区贡献对 Conductor 发展的重要价值。
Cassandra 持久层
为了实现数据存储的水平扩展,并应对大量并发工作流执行,例如每天数百万级别的工作流,我们选择使用 Cassandra 来提供弹性扩展能力,并满足高吞吐需求。
外部有效载荷存储
我们实现了外部有效载荷存储,目的是防止 Conductor 被当作数据持久化系统使用,同时减轻后端数据存储的压力。
在工作流系统中,任务输入输出可能包含较大的数据对象。如果这些数据全部直接存储在 Conductor 的核心存储中,系统的可维护性和扩展性都会受到影响。外部有效载荷存储可以将大体积数据转移到外部存储系统中,而 Conductor 只保留必要引用,从而让编排引擎专注于工作流执行本身。
动态工作流执行
有些场景需要执行大量不同的工作流定义,甚至是任意数量的工作流定义;还有一些场景只是为了测试、分析或一次性任务而运行临时工作流。如果每次都要先将工作流定义注册到元数据存储中,再执行一次工作流,就会带来不必要的开销。
动态创建和执行工作流的能力消除了这一障碍。通过这项能力,用户可以在运行时创建并执行工作流,而不必提前将所有定义注册到系统中。这也是我们与开源社区协作取得的又一项重要成果。
工作流状态监听器
Conductor 可以配置为在工作流完成或终止时,向外部系统或队列发布通知。工作流状态监听器提供了一组钩子,可以连接到你选择的任何通知系统。
社区贡献了一个实现方案,可以根据工作流状态向 dyno 队列发布消息。随后,可以在这些队列上配置事件处理器,在工作流终止时触发特定工作流或任务,完成后续操作。
批量工作流管理
从可运维性的角度来看,工作流层面的批量操作一直都非常必要。
当系统规模扩大后,下游依赖异常、工作进程故障或任务执行错误,都可能导致大量任务失败。此时,能够对工作流执行批量操作就显得尤为重要。批量 API 让运维人员可以从更宏观的层面对系统中正在执行的工作流进行控制。
将 Elasticsearch 与持久化机制解耦
过去,索引层和持久化层之间存在一定耦合。我们通过将索引层迁移到独立的持久化模块,并暴露 workflow.elasticsearch.instanceType 属性来选择索引引擎类型,消除了这种相互依赖关系。
此外,我们还通过 ExecutionDAOFacade 将编排逻辑从主持久化层上移到服务层,从而进一步解耦索引器和持久化层。
支持 Elasticsearch 5/6
作为 v2.x 版本主要升级的一部分,Conductor 新增了对 Elasticsearch 5 和 6 的支持。本次升级还提供了使用 Elasticsearch RestClient 的选项,而不再强制依赖早期版本中的 Transport Client。
这使得在 Conductor 部署中使用托管 Elasticsearch 集群成为可能。
任务速率限制与并发执行限制
任务速率限制可以帮助实现任务调度层面的限流。
任务定义中的 rateLimitFrequencyInSeconds 参数用于设置任务执行的时间窗口,rateLimitPerFrequency 则定义了在该时间窗口内可以调度的任务数量。
另一方面,concurrentExecLimit 用于限制任务并发执行数量。也就是说,在任意给定时间点,已调度任务的总数都会低于 concurrentExecLimit。
这些参数可以组合使用,以实现所需的节流和速率限制策略。
API 验证
验证能力是 Conductor 1.x 中缺失的一项核心能力。为了提升易用性和可运维性,我们在新版本中增加了验证功能。
实践证明,这项能力极大地帮助用户在创建工作流定义和任务定义时发现错误。验证机制会要求用户先创建并注册任务定义,然后才能注册使用这些任务的工作流定义。它还会确保工作流定义格式正确,并检查工作流中各个任务的输入输出连接是否合理。
如果系统发现异常,会向用户返回详细错误信息,说明失败原因,帮助用户更快定位问题。
开发者实验室、日志与指标
我们持续改进日志记录和指标体系,并同步更新文档,以反映 Conductor 的最新状态。
为了提供更流畅的入门体验,我们创建了开发者实验室,用于指导用户创建任务和工作流定义、管理工作流生命周期、配置带有事件的高级工作流等。同时,开发者实验室也会简要介绍 Conductor API、用户界面和其他模块。
Conductor 新增任务类型
系统任务已经被证明在定义工作流结构和控制流程方面非常有价值。因此,Conductor 2.x 为系统任务新增了多项能力,其中大部分来自社区贡献。
Lambda 任务
Lambda 任务会在工作流运行时使用 Nashorn JavaScript 求值引擎执行临时逻辑。它允许用户通过简单的 JavaScript 表达式直接完成轻量级求值操作,而不必为了简单判断专门创建一个工作进程。
Terminate 任务
当工作流逻辑需要以特定输出终止时,Terminate 任务非常有用。
例如,如果某个决策任务的评估结果为假,而我们不希望继续执行工作流中的剩余任务,那么相比创建一个包含任务列表的决策任务,甚至创建一个空任务列表,使用 Terminate 任务来限定决策范围并终止工作流执行会更加清晰。
Exclusive Join 任务
Exclusive Join 任务用于捕获决策流程中的任务输出。它适用于将某个决策分支中的任务输出连接到后续任务输入的场景。
这些数据只在工作流执行期间可用,而 Exclusive Join 任务可以用来收集任意决策分支中某个任务的输出。
有关新增功能的详细实现细节,可参阅相关文档。
Conductor 工作流编排的未来路线图
我们希望继续为 Conductor 增加更多功能和改进。下面这份清单可以视为一份长期路线图。它并不完整,我们也非常欢迎社区提出新的想法和建议。以下项目排名不分先后。
高级事件管理:事件聚合与分发
目前,事件的生成和处理机制相对简单:一个事件任务只能创建一条消息,一个任务也只能等待一个事件。
我们设想引入事件聚合和分发机制,使 Conductor 能够覆盖更多场景。一个初步设想是:允许一个任务等待多个事件,也允许一个事件推动多个任务继续执行。
用户界面改进
当前 UI 已经提供了一种简洁方式,用于可视化和跟踪工作流执行情况。但我们仍希望通过以下能力进一步增强它:
- 在用户界面中创建元数据对象
- 支持直接启动工作流
- 可视化执行指标
- 提供展示异常值的管理员仪表盘
新增任务类型:Goto、Loop 等
Conductor 一直使用有向无环图(DAG)结构来定义工作流。Goto 和 Loop 任务确实对应一些有效的业务场景,但它们会偏离 DAG 结构。
我们希望在不破坏现有工作流执行规则的前提下,增加对这些任务类型的支持。这将解锁更多用例,例如将数据流式传输到任务,或者在工作流中重复执行一组任务。
支持可复用的通用任务
我们同样看到了共享可复用任务的价值。这类任务可以执行特定操作,并被不同团队直接复用。
在内部部署 Conductor 时,我们会添加一些特定于内部服务的任务,用户可以直接使用这些任务,而不必从头开始重新创建。例如,我们提供了一个容器启动任务,使用户可以在工作流执行过程中启动新的容器。
我们希望进一步扩展这一思路,让 Conductor 能够提供一个通用任务库。
基于推送的任务调度接口
当前 Conductor 架构基于工作节点轮询机制,由工作节点主动拉取待执行任务。
我们希望增强 gRPC 模块,利用双向通道在任务调度完成后立即将任务推送给工作节点。这样可以减少网络流量、降低服务器负载,并避免冗余的客户端调用。
验证任务输入键和输出键
这项能力旨在为任务提供类型安全保障,并为任务定义提供一个参数化接口。这样一来,任务一旦注册,就可以在 Conductor 中被完整复用。
它也会形成一种契约,让用户能够浏览可用任务定义,并在自己的工作流中使用这些任务,即使这些任务由其他团队或用户实现。该功能还会涉及用户界面的增强,以便展示这类契约信息。
在 Cassandra 中实现 MetadataDAO
如前所述,Cassandra 模块目前仅提供了工作流执行持久化的部分实现,尚未实现元数据持久化能力。我们正在努力尽快补齐这一功能。
任务完成时的可插拔通知
类似于工作流状态监听器,我们希望提供一个可扩展接口,用于在任务执行完成时发送通知。
发布官方 Python 客户端
我们看到 Python 客户端在社区中得到了广泛使用。然而,目前包管理平台上还没有官方 Python 客户端,而且现有客户端也缺少 Java 客户端中的一些新增功能。
我们希望实现功能上的完全一致,并从 Conductor 的代码库中发布客户端,随后实现客户端到包管理平台的自动化发布流程。
从关键路径中移除 Elasticsearch
Elasticsearch 在 Conductor 中非常有用,但我们希望对于尚未配置 Elasticsearch 的用户而言,它应当是一个可选组件。
这意味着,我们需要将 Elasticsearch 从工作流关键执行路径中移除,使其作为可选层存在。
可插拔身份认证与授权
Conductor 目前不支持 API 或 UI 层面的身份认证和授权。我们认为这将带来很大价值,也是社区中经常被提出的需求。
验证与测试
“空运行”能力,也就是在不真正通过工作进程和全部相关设置执行工作流的情况下,对工作流定义进行评估,可以让执行路径的测试和调试变得更加容易。
Conductor 开源社区参与
如果你希望成为 Conductor 社区的一员,并为路线图中的某个项目,或者你认为能够带来显著价值的项目做出贡献,可以阅读贡献指南获取说明,也可以在用户论坛中发起讨论。
我们也强烈鼓励大家对基于 Conductor 构建的自定义功能进行完善、通用化,并与社区分享。
我们非常感谢社区的积极参与,也为社区为 Conductor 做出的重要贡献感到自豪。我们希望在此基础上继续前进,在强大社区的支持下,让 Conductor 被更广泛地采用。
对于这类长期演进的开源项目而言,除了代码贡献和架构设计,任务分配、路线图管理、文档协同和跨角色沟通同样重要。比如 Worktile 这类通用项目协作系统,可以承接任务、项目、文档、目标、日历和审批等协作场景,帮助不同成员围绕同一项目目标高效配合。
Conductor 由某海外技术团队的媒体工作流基础设施团队维护。如果你喜欢构建分布式系统带来的挑战,并对大规模内容与工作室工程生态感兴趣,欢迎与相关团队取得联系。
总体来看,Conductor v2.0 及后续版本的演进,反映了工作流编排引擎在微服务架构中的关键价值:它不仅要负责复杂业务流程的自动化执行,还要在任务调度、数据持久化、事件管理、可观测性、扩展性和社区生态之间取得平衡。对于需要管理大规模分布式工作流的团队而言,这类工作流编排实践具有很高的参考价值。
文章包含AI辅助创作:Conductor 工作流编排引擎演进:v2.0 架构、任务调度与微服务编排实践,发布者:shang,转载请注明出处:https://worktile.com/kb/p/3980894
微信扫一扫
支付宝扫一扫