阿里妹导读:搜索中台建设过程中,单个系统不再能满足复杂业务的需求,更多时候需要多个子系统互相协作,异步地按照指定流程完成一项特定的功能。例如一个应用的上线流程依次需要调用配置同步模块、监控模块、资源更新模块、冒烟模块、引擎创建模块,流程的运行中又有分支判断、上下文传递、失败重试等需求。基于这种需求,Maat将各类流程化的任务集中管理,各个任务节点以分布式的方式运行在不同容器内,保证流程高效稳定地运行。
背景
什么是Maat?
Maat是一个基于开源项目Airflow的流程调度系统,它支持用户自定义地组装流程节点,流程可以在用户指定的时间触发(支持crontab格式),或由用户手动触发。
Maat的所有节点分布式地运行在Hippo上,由Drogo调度。用户可以创建自己的调度节点和执行节点,达到资源隔离的目的。
用户可以通过配置的方式安装自己执行节点的运行环境,也可以配置执行节点的副本数。
下图展示了一个任务的一次调度流程:
为什么要做Maat?
我们在项目的开发过程中,经常遇到一些流程化/定时调度的需求,如上线发布流程、定时分析任务流程等。对于这些流程化的调度任务,我们尝试过自己开发了一套流程调度系统,也尝试过接入集团的工作流,但难免会遇到一些问题:
业务代码和调度代码耦合严重,修改流程基本需要入侵到代码级别,业务代码的发布影响调度。
对于这些调度任务,没有一个统一管控的系统,难以管理和追溯。
多分支的复杂流程不能很好支持,上下文传递场景不能很好支持。
缺少可视化的UI,用户使用不友好。
技术选型
定时任务&流程任务的调度是一个通用的需求,集团内的产品如D2、工作流,开源的产品如Airflow、Quartz等。
★ D2
D2是基于ODPS生态的一套流程调度系统,承载集团基于ODPS数据产出的调度任务。支持用户自定义编写脚本,支持定时任务触发和手动触发(补运行的方式),适合基于数据状态的任务流程调度(如根据数据的产出执行任务流),由D2团队专门维护,有较好的UI。
但它有一些不足:
D2的DAG调度是一张大图,每天需要运行的每个节点及拓扑关系是根据前一天的全局的拓扑关系计算得出的,所以新创建/修改的任务理论上只能第二天生效,如果想立即生效需要采用补运行的方式。业务上经常会有任务的变动(如任务配置或调度时间),或手动触发一个调度的场景(如随时发生的上线流程、全量流程),使用D2对业务不是很灵活,也不符合D2的使用场景。
不支持流程上下文的传递,业务上对上下文的传递比较强烈,经常有上个节点产出某个值,下个节点需要使用。
缺乏对搜索生态的支持。搜索技术部整个底层架构有自己的一套生态,如调度(Hippo,Drago)、报警(Kmon)。使用D2,不能充分享受搜索技术生态带来的好处,对于之后的单元化部署也会带来问题。
★ 工作流
集团工作流是集团审批流程的一个通用调度引擎,很多产品的审批流程都是基于集团工作流的,同时它也可以作为一个简易的任务调度流程使用,我们在Maat之前也使用集团工作流作为我们流程任务的调度引擎。它支持手动触发,支持以HSF的方式调用外部系统,支持上下文传递。但它在配置上较为复杂,且支持外部系统的调用方式有限。
★ Quartz
Quartz是Java开源的任务调度框架。它支持分布式调度、支持任务持久化、支持定时任务,但不支持流程调度,且任务配置需要耦合在调度系统中,任务的热加载需要做一些改造。
★ Airflow
开源项目Airflow是一套分布式的流程调度系统,它的优势如下:
业务代码和调度系统解耦,每个业务的流程代码以独立的Python脚本描述,里面定义了流程化的节点来执行业务逻辑,支持任务的热加载。
完全支持crontab定时任务格式,可以通过crontab格式指定任务何时进行。
支持复杂的分支条件,每个节点单独设定触发时机,如父节点全部成功时执行、任意父节点成功时执行。
有一套完整的UI,可视化展现所有任务的状态及历史信息。
外部依赖较少,搭建容易,仅依赖DB和rabbitmq。
有同学问到Luigi与Airflow的对比,个人感觉都是基于pipline的一个任务调度系统,功能也大同小异,Airflow属于后来居上,功能更强,找到一篇同类产品的对比。
经过一段时间的调研,我们选用Airflow作为我们的原型开发一套分布式任务调度系统,它功能全面,基本满足业务需求,在功能上扩展相对方便,外部依赖较少,和搜索生态对接相对容易。
原生Airflow的问题
Airflow可以解决流程调度中面临的许多问题,但直