Netflix Conductor:微服务编排引擎
原文:Netflix Conductor : A microservices orchestrator
作者:Viren Baraiya, Vikram Singh 翻译:Daisy 责编:仲培艺
Conductor是Netflix开源的一款微服务编排引擎,托管在GitHub上,使用Apache License 2.0许可。
Conductor是受到Netflix需要运行全球流媒体业务流程的启发,而构建的基于云的微服务编排引擎。
下面是一些流程案例:
- 用来提取内容的Studio合作伙伴集成;
- 基于IMF的内容提取;
- 在Netflix中设置新标题流程;
- 内容提取、编码和部署到CDN。
通常,其中的部分流程会专门使用pub/sub组合直接REST调用,并使用一个数据库来管理状态编排。但随着微服务数量和流程复杂性的增加,如果没有*协调器,那么获得这些分布式工作流的难度就会加大。
为什么不使用对等编排?
Pub/sub模型适用于一些简单的流程,对等编排很难进行扩展,并且很快就发现了很多问题:
- 流程流被嵌套在多个应用代码内;
- 通常,围绕输入/输出、SLAs等方面存在的紧耦合和假设,导致很难适应不断变化的需求;
- 几乎没有办法系统地回答:“进程完成情况”。
Netflix将Conductor构建为一个编排引擎,可以满足以下需求,在应用中消除样板需求,并提供一个反应流:
- 使用JSON DSL描述的工作流蓝图;
- 跟踪和管理工作流;
- 可以暂停、恢复和重新启动任务;
- 可视化的用户流程界面;
- 可根据需要,同步处理所有执行任务;
- 处理工作流能够扩展到百万级别;
- 可抽离客户端的排队服务;
- 支持HTTP或其他传输方式,如gRPC。
Conductor已经在Netflix内部使用了近一年。Netflix称其已经帮助编排超过260万个流程,从简单的线性工作流程到运行多天的非常复杂的动态工作流程都有。
该引擎的核心是状态机服务,也叫作决策器服务。当工作流事件(例如:任务完成、失败等),决策器将工作流蓝图与工作流的当前状态组合,识别下一个状态,并调度适当的任务或更新工作流的状态。
Decider使用分布式队列管理任务调度。Netflix一直在Dynomite上使用dyno-queues来管理分布式延迟队列。Dynomite和dyno-queues都已经开源,这里是当初的开源文章。
任务实现Worker
工作流任务由Worker实现,并通过API层进行通信。Worker通过编排引擎调用REST端点或者通过实现定期检查挂起的任务轮询循环来实现。轮询模型允许用户在Workers上处理背压,并在可能时,基于队列深度提供自动可伸缩性。Conductor提供API来检查每个Worker的工作负载大小,这样就可以自动伸缩Worker实例。
- API层——使用HTTP或gRPC轻松集成各个不同的客户端。
- 存储——使用Dynomite作为存储方案,Elasticsearch作为索引流执行方案。存储API是可插拔的,可用于各种存储系统,包括传统的RDBMS或Apache Cassandra。
核心概念
工作流定义
工作流是使用基于JSON的DSL定义的,工作流蓝图定义了需要执行的一系列任务。要么是控制任务(例如:叉、连接、决策、子工作流等),要么是Worker任务。工作流还可以进行版本控制,可以灵活地进行升级和迁移。
工作流定义概述:
{
"name": "workflow_name",
"description": "Description of workflow",
"version": 1,
"tasks": [
{
"name": "name_of_task",
"taskReferenceName": "ref_name_unique_within_blueprint",
"inputParameters": {
"movieId": "${workflow.input.movieId}",
"url": "${workflow.input.fileLocation}"
},
"type": "SIMPLE",
... (any other task specific parameters)
},
{}
...
],
"outputParameters": {
"encoded_url": "${encode.output.location}"
}
}
任务定义
每个任务行为都由其任务定义模板控制。每个任务定义会提供任务参数,例如,超时,重试策略等。任务有两种,一个是Worker,运行在远端机器上的用户任务;一个System,运行在引擎的JVM上的任务。后者用来对Worker执行任务进行branch、fork、join。Worker任务通过HTTP或者gRPC(基于HTTP/2)和Conductor通信。
任务定义JSON代码片段:
{
"name": "encode_task",
"retryCount": 3,
"timeoutSeconds": 1200,
"inputKeys": [
"sourceRequestId",
"qcElementType"
],
"outputKeys": [
"state",
"skipped",
"result"
],
"timeoutPolicy": "TIME_OUT_WF",
"retryLogic": "FIXED",
"retryDelaySeconds": 600,
"responseTimeoutSeconds": 3600
}
输入/输出
输入任务JSON代码片段:
{
"name": "name_of_task",
"taskReferenceName": "ref_name_unique_within_blueprint",
"inputParameters": {
"movieId": "${workflow.input.movieId}",
"url": "${workflow.input.fileLocation}"
},
"type": "SIMPLE"
}
未来计划
- 支持AWS Lambda(或类似)函数作为无服务器任务;
- 与容器编排框架进行更紧密的集成,这样工作实例就可以自动扩展;
- 记录每个任务的执行数据;
- 从UI上实现创建和管理工作流蓝图。