背景

随着公司业务越来越多,越来越复杂,执行的脚本已经达到了近百个,像以前那样直接使用linux的crontab来执行脚本,已经满足不了业务需求了。
举个例子:我们的大数据团队,他们提供了数据订阅功能给到合作伙伴和公司高管查看统计报表,他们每天都会对所有基础数据进行一些预加工处理,输出的数据,存储到多张不同业务的 Hive 表中,然后对 Hive 中多个表的数据,按照各种关系合并处理,得到一个明细数据表,将明细数据按预定义的维度进行复杂的业务统计分析,得到每日统计报表信息,将报表数据生成邮件、附件发出来给到各需求方,同时将统计分析得到的结果数据回流到业务系统中,供业务调用使用。
在这个例子中,我们发现有很多复杂的处理,且大部分步骤都需要跨越不同的程序,而且全部操作处理过程较长,往往需要几十分钟或几个小时。在整个业务过程中,什么时候开始启动,拉起下一步,某个步骤出错以后具体如何重试处理(如何清理数据、回到哪一步进行重试,超时如何配置等),都需要有某个任务调度机制来处理。
在以往的实践中,我们一般直接使用 linux 的 crontab 来定义简单的任务调度。但 crontab 功能简单,只具有定时拉起命令脚本的功能,不具备流程管理、依赖管理的能力。
后来人们针对 crontab 的痛点,开发出来了ooize、Azkaban、Cascading、Hamake 等开源的 Hadoop 任务调度框架。而 Azkaban 则是其中的佼佼者,轻量级、分布式的工作流任务调度框架,具有使用方便、能严格控制操作权限等优点。

Azkaban是什么?

Azkaban 是由 Linkedin 公司推出的一个批量工作流任务调度器,主要用于在一个工作流内以一个特定的顺序运行一组工作和流程,它的配置是通过简单的 key:value键值对的方式,通过配置中的 dependencies 来设置依赖关系,这个依赖关系必须是无环的,否则会被视为无效的工作流。Azkaban 使用 job 配置文件建立任务之间的依赖关系,并提供一个易于使用的 web 用户界面维护和跟踪你的工作流。
在介绍 Azkaban 之前,我们先来看一下现有的两个工作流任务调度系统。知名度比较高的应该是Apache Oozie,但是其配置工作流的过程是编写大量的XML配置,而且代码复杂度比较高,不易于二次开发。另外一个应用也比较广泛的调度系统是 Airflow,但是其开发语言是Python。由于我们团队内部没有使用Python的,Java的倒是有,所以选型的时候就被淘汰掉了。我们选择 Azkaban 的原因基于以下几点:

  • 提供功能清晰,简单易用的 Web UI 界面,任务可在线追踪,在线看日志,在线触发执行,无需再登录到服务器
  • 提供 job 配置文件快速建立任务和任务之间的依赖关联,并且变量可编程化
  • 调度执行 exec-A 执行失败调度到 exec-B 执行,以及重试机制
  • 资源优选 exec-A 和 exec-B 谁资源空闲用谁来执行
  • 完整的邮件短信通知机制

Azkaban的适用场景

实际项目中经常有这些场景:每天有一个大任务,这个大任务可以分成A,B,C,D四个小任务,A,B任务之间没有依赖关系,C任务依赖A,B任务的结果,D任务依赖C任务的结果。一般的做法是,开两个终端同时执行A,B,两个都执行完了再执行C,最后再执行D。这样的话,整个的执行过程都需要人工参加,并且得盯着各任务的进度。但是我们的很多任务都是在深更半夜执行的,通过写脚本设置 crontab 执行。其实,整个过程类似于一个有向无环图(DAG)。每个子任务相当于大任务中的一个流,任务的起点可以从没有度的节点开始执行,任何没有通路的节点之间可以同时执行,比如上述的A,B。总结起来的话,我们需要的就是一个工作流的调度器,而 Azkaban 就是能解决上述问题的一个调度器。

Azkaban架构

Azkaban 在 LinkedIn 上实施,以解决 Hadoop 作业依赖问题。我们有工作需要按顺序运行,从 ETL 工作到数据分析产品。最初是单一服务器解决方案,随着多年来 Hadoop 用户数量的增加,Azkaban 已经发展成为一个更强大的解决方案。
Azkaban由三个关键组件构成:

  • 关系型数据库(MySQL)
  • AzkabanWebServer
  • AzkabanExecutorServer

azkaban2overviewdesign

关系型数据库(MySQL)

Azkaban 使用数据库存储大部分状态,AzkabanWebServer 和 AzkabanExecutorServer 都需要访问数据库。
AzkabanWebServer 使用数据库的原因如下:

  • 项目管理:项目、项目权限以及上传的文件
  • 执行流状态:跟踪执行流程以及执行程序正在运行的流程
  • 以前的流程/作业:通过以前的作业和流程执行以及访问其日志文件进行搜索
  • 计划程序:保留计划作业的状态
  • SLA:保持所有的SLA规则

AzkabanExecutorServer使用数据库的原因如下:

  • 访问项目:从数据库检索项目文件
  • 执行流程/作业:检索和更新正在执行的作业流的数据
  • 日志:将作业和工作流的输出日志存储到数据库中
  • 交互依赖关系:如果一个工作流在不同的执行器上运行,它将从数据库中获取状态

AzkabanWebServer

AzkabanWebServer 是整个 Azkaban 工作流系统的主要管理者,它负责 project 管理、用户登录认证、定时执行工作流、跟踪工作流执行进度等一系列任务。同时,它还提供 Web 服务操作的接口,利用该接口,用户可以使用curl或其他ajax的方式,来执行 azkaban 的相关操作。操作包括:用户登录、创建project、上传workflow、执行workflow、查询 workflow 的执行进度、杀掉 workflow 等一系列操作,且这些操作的返回结果均是 json 的格式。并且 Azkaban 使用方便,Azkaban 使用以.job为后缀名的键值属性文件来定义工作流中的各个任务,以及使用 dependencies 属性来定义作业间的依赖关系链。这些作业文件和关联的代码最终以*.zip的方式通过 Azkaban UI 上传到 Web 服务器上。

AzkabanExecutorServer

以前版本的 Azkaban 在单个服务中具有 AzkabanWebServer 和 AzkabanExecutorServer 功能,目前 Azkaban 已将AzkabanExecutorServer 分离成独立的服务器,拆分 AzkabanExecutorServer 的原因有如下几点:

  • 某个任务流失败后,可以更方便的将其重新执行
  • 便于Azkaban升级

AzkabanExecutorServer 主要负责具体的工作流的提交、执行,可以启动多个执行服务器,它们通过 mysql 数据库来协调任务的执行。

Azkaban作业流执行过程

  • Webserver 根据内存中缓存的各 Executor 的资源状态(Webserver 有一个线程会遍历各个 active executor,去发送http 请求获取其资源状态信息缓存到内存中),按照选择策略(包括 executor 资源状态、最近执行流个数等)选择一个executor 下发作业流
  • executor 判断是否设置作业粒度分配,如果未设置作业粒度分配,则在当前 executor 执行所有作业;如果设置了作业粒度分配,则当前节点会成为作业分配的决策者,即分配节点
  • 分配节点从zookeeper获取各个executor的资源状态信息,然后根据策略选择一个executor分配作业
  • 被分配到作业的executor即成为执行节点,执行作业,然后更新数据库

Azkaban架构的三种运行模式

在版本3.0中,Azkaban提供了以下三种模式:

  • solo server mode:最简单的模式,数据库内置的 H2 数据库,AzkabanWebServer 和 AzkabanExecutorServer 都在一个进程中运行,任务量不大项目可以采用此模式
  • two server mode:数据库为 MySQL,管理服务器和执行服务器在不同进程,这种模式下,AzkabanWebServer 和AzkabanExecutorServer 互不影响
  • multiple executor mode:该模式下,AzkabanWebServer 和 AzkabanExecutorServer 运行在不同主机上,且AzkabanExecutorServer 可以有多个

目前我们采用的是 multiple executor mode 方式,分别在不同的主机上部署多个 AzkabanExecutorServer 以应对高并发定时任务执行的情况,从而减轻单个服务器的压力。

最后修改:2023 年 09 月 11 日
如果觉得我的文章对你有用,请随意赞赏