Netflix Conductor:微服务编排器

翻译自 https://medium.com/netflix-techblog/netflix-conductor-a-microservices-orchestrator-2e8d4771bf40

Netflix 内容平台工程团队支撑了许多业务,这些业务流程由微服务任务异步驱动的。其中一些任务是持续数天的长流程。这些流程在为全球观众提供字幕方面发挥着至关重要的作用。

这些流程包括:

  • Studio 合作伙伴内容集成
  • 来自合作伙伴的基于 IMF 的内容集成
  • 在 Netflix 中设置新标题
  • 接收内容,编码和部署到 CDN

传统做法中,这些流程是临时编排的,使用 pub/sub(发布/订阅模型)组合起来,直接进行 REST 调用,并使用数据库来管理状态。然而,随着微服务数量和流程复杂度的增加,如果没有中央协调器,理解这些分布式工作流会变得非常困难。

我们将 Conductor 作为“编排引擎”构建,以满足以下需求,在应用程序中消除了模板,同时提供反应流:

  • 使用基于 JSON DSL 的 Blueprint 定义执行流程
  • 跟踪并管理工作流
  • 能够暂停,恢复和重新启动流程
  • 用户界面可视化处理流程
  • 能够在需要时同步处理所有任务
  • 能够扩展为百万级并发运行的流程
  • 由客户端提取出来的的队列服务支撑
  • 能够通过 HTTP 或其他方式操作,例如 GRPC

Conductor 旨在满足上述需求,现在已在 Netflix 使用了将近一年。迄今为止,它调度超过 260 万个工作流,包括从简单的线性工作流到运行多天的非常复杂的动态工作流。

在线 Conductor 已经在社区开源,我们希望 Conductor 可以服务于有类似需求的场景,并提升其能力。附上Conductor 的开发人员文档。

为什么不使用点对点编排

使用点对点任务编排很难随着业务需求和复杂度增长的而完成扩展。Pub/sub(发布/订阅模型)模型适用于最简单的流程,但是该方案的也存在一些问题,包括:

  • 流程分散在多个应用程序的代码中
  • 通常围绕输入/输出,SLA 等存在很强的耦合以及假定,使得此方案更加难以适应变化的需求
  • 几乎没有办法系统性地回答“某个电影的搭建还剩下什么任务有待完成的”?

为什么是微服务

在微服务领域,许多业务流程自动化都是通过协调服务来驱动的。Conductor 支持跨服务的协调,同时提供交互式控制和可视性。能够跨服务进行微服务协调,有助于我们利用现有服务构建新流程或更新现有流程,从而非常快速地接入 Conductor。

架构总览

Netflix Conductor:微服务编排器_第1张图片引擎的核心是状态机服务,即 Decider 服务。当工作流事件发生时(例如任务完成,失败等),Decider 将工作流 blueprint 与工作流的当前状态相匹配,识别下一个状态,并安排适当的任务,或更新工作流的状态。Decider 与分布式队列一起使用来管理调度计划任务。我们使用dyno-queues作为分布式延迟队列,dyno-queues使用dynomite作为 K-V 存储。该队列已于今年早些时候开源,知详情请看这里。

Task Worker 的实现

task 由 worker 应用程序实现,通过 API 层进行通信。woker 有两种实现方式,由流程引擎调用的 REST 接口,或者通过定期检查挂起任务的状态。Worker 实际上是幂等的无状态函数。轮询模型允许处理 worker 的压力,并在可能的情况下根据队列深度支持自动伸缩。Conductor 提供 API 以检查 worker 的工作负载大小。Netflix Conductor:微服务编排器_第2张图片

API 层

API 通过 HTTP 提供 - 使用 HTTP 可以轻松地与不同客户端集成。添加其他协议(例如 gRPC)也是很简单的。

存储

我们使用 Dynomite 作为存储引擎,Elasticsearch 来索引执行流程。存储 API 是可插拔的,可以适用于各种存储系统,包括传统的 RDBMS 或 Apache Cassandra 这样的 no-sql 存储。

核心观点

工作流定义

使用基于 DSL 的 JSON 定义工作流。工作流 blueprint 定义了一系列需要执行的任务。每个任务要么是一个控制任务(例如,fork,join,决策,子工作流等)要么是一个 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 任务,也可以是由编排服务执行的系统任务。Conductor 提供一些开箱即用的系统任务,例如 Decision,Fork,Join,Sub Workflows,并且允许加入自定义系统任务的 SPI。我们已经添加了对 HTTP 任务的支持,可以辅助调用 REST 服务。任务定义示例

{"name": "encode_task","retryCount": 3,"timeoutSeconds": 1200,"inputKeys": ["sourceRequestId","qcElementType"],"outputKeys": ["state","skipped","result"],"timeoutPolicy": "TIME_OUT_WF","retryLogic": "FIXED","retryDelaySeconds": 600,"responseTimeoutSeconds": 3600}   

输入/输出

任务的输入是一种映射,其作为工作流实例化的一部分或某些其他任务的输出。允许将来自工作流或其他任务的输入/输出作为随后执行的任务的输入。例如,可以将编码任务的输出作为输入提供给发布任务以部署到 CDN。

定义任务输出示例

{  "name": "name_of_task",  "taskReferenceName": "ref_name_unique_within_blueprint",  "inputParameters": {    "movieId": "${workflow.input.movieId}",    "url": "${workflow.input.fileLocation}"  },  "type": "SIMPLE"}   

### 示例 Netflix Conductor:微服务编排器_第3张图片 这里共涉及 3 个 worker 任务和一个控制任务:

  1. 内容检查:检查输入文件是否正确/完整
  2. 编码:生成视频编码
  3. 发布:发布到 CDN

这三个任务由不同的 worker 实现,使用任务 API 轮询待处理的任务。这些任务是幂等任务,worker 根据给予任务的输入进行操作,执行处理流程并更新状态。

在完成每个任务时,Decider 会根据 blueprint(对应于工作流实例的版本)评估工作流实例的状态,并标识要调度的下一组任务,或者在完成所有任务后标记工作流为完成。

UI

UI 是监控和排除工作流程执行故障的主要手段。通过基于各种参数(包括输入/输出参数)的搜索,UI 实现了处理流程的可视化,并提供 blueprint 和其采取的执行路径的可视化表示,以更好地理解流程执行的过程。对于每个工作流实例,UI 提供每个任务执行的详细信息,并提供以下详细信息:

  • 任务调度的时间戳,worker 接收并完成任务的时间戳
  • 如果任务失败了,失败的原因
  • 重试次数
  • 执行任务的主机
  • 任务的输入和输出

这里是生成性能数字的 kitchen sink 工作流的 UI 片段:

Netflix Conductor:微服务编排器_第4张图片


本文首发于 GitChat,未经授权不得转载,转载需与 GitChat 联系。

阅读全文: http://gitbook.cn/gitchat/activity/5db939223589de50879b01f7

您还可以下载 CSDN 旗下精品原创内容社区 GitChat App ,阅读更多 GitChat 专享技术内容哦。

FtooAtPSkEJwnW-9xkCLqSTRpBKX

你可能感兴趣的:(Netflix Conductor:微服务编排器)