Loading [MathJax]/jax/input/TeX/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Azkaban集群内部调度原理分析

Azkaban集群内部调度原理分析

作者头像
用户1257215
发布于 2018-07-27 01:49:41
发布于 2018-07-27 01:49:41
2.6K00
代码可运行
举报
文章被收录于专栏:架构师之旅架构师之旅
运行总次数:0
代码可运行

Azkaban是一个非常简单实用,而且开源的作业调度系统。在2.x版本中不支持集群模式部署,在3.x版本中支持集群模式部署,适用于作业量比较大一些的应用场景。有关Azkaban更多详细信息,如特点、功能、特性、作业定义等,可以参考官方文档,这里不再详述。

Azkaban集群架构

下面我们看一下Azkaban集群模式的架构,如下图所示:

从上图可见,Azkaban集群部署模式,主要有3个核心的组件:

  • Azkaban WebServer

Azkaban WebServer,是整个调度集群的核心,负责所有作业的管理和调度。

  • Azkaban ExecutorServer

Azkaban ExecutorServer,整个调度集群中实际运行作业的节点,该类节点可能是作为一个作业提交的客户端,比如Spark on YARN部署模式下,cluster运行模式时只作为客户端使用,client运行模式时会有部分计算逻辑;比如普通的Java程序需要处理量级较小的数据作业,这时Executor Server节点可能有较大的工作负载,占用较多节点资源(内存、CPU)。

  • DB

DB,是集群中所有节点运行共用的数据存储,包含作业信息、各种调度元数据等等。

核心调度概述

Azkaban WebServer需要根据Executor Server的运行状态信息,选择一个合适的Executor Server来运行WorkFlow,然后会将提交到队列中的WorkFlow调度到选定的Executor Server上运行。我们整理了与核心调度相关的各个组件,主要包括Azkaban WebServer端和Azkaban ExecutorServer端,他们之间的关系如下图所示:

其实,从调度层面来看,Azkaban WebServer与Executor Server之间的交互方式非常简单,是通过REST API的方式来进行交互,基本的模式是,Azkaban WebServer根据调度的需要,主动调用Executor Server暴露的REST API来获取相应的资源信息,比如Executor Server的状态信息、分配WorkFlow到指定Executor Server上运行,等等。 我们可以在QueueProcessorThread.selectExecutorAndDispatchFlow()方法中看到,选择Executor Server并进行调度的实现,代码片段如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1 final Executor selectedExecutor = selectExecutor(exflow, availableExecutors);
 2if (selectedExecutor != null) {
 3  try {
 4    dispatch(reference, exflow, selectedExecutor);
 5    ExecutorManager.this.commonMetrics.markDispatchSuccess();
 6  } catch (final ExecutorManagerException e) {
 7    ExecutorManager.this.commonMetrics.markDispatchFail();
 8    logger.warn(String.format(
 9        "Executor %s responded with exception for exec: %d",
10        selectedExecutor, exflow.getExecutionId()), e);
11    handleDispatchExceptionCase(reference, exflow, selectedExecutor,
12        availableExecutors);
13  }
14}

QueueProcessorThread是运行在Azkaban WebServer端的一个线程,它在ExecutorManager中定义,是内部调度中最核心的线程。selectExecutor()方法处理如何选择一个合适的Executor Server,然后通过dispatch()方法将需要运行的WorkFlow调度到该Executor Server上运行。

选择Executor Server

Azkaban WebServer选择Executor,调用selectExecutor()方法,实现如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1private Executor selectExecutor(final ExecutableFlow exflow,
 2    final Set<Executor> availableExecutors) {
 3  Executor choosenExecutor =
 4      getUserSpecifiedExecutor(exflow.getExecutionOptions(),
 5          exflow.getExecutionId());
 6  // If no executor was specified by admin
 7  if (choosenExecutor == null) {
 8    logger.info("Using dispatcher for execution id :"
 9        + exflow.getExecutionId());
10    final ExecutorSelector selector = new ExecutorSelector(ExecutorManager.this.filterList,
11        ExecutorManager.this.comparatorWeightsMap);
12    choosenExecutor = selector.getBest(availableExecutors, exflow);
13  }
14  return choosenExecutor;
15}

首先,查看当前exflow的配置中,是否要求将该exflow调度到指定的Executor Server上运行,如果是的话,则会返回该指定的Executor Server的信息,后续直接调度到该Executor Server上;否则会按照一定的计算规则去选出一个Executor Server。

在创建ExecutorSelector时,传入参数值ExecutorManager.this.filterList,该filterList是从azkanban.properties文件中读取azkaban.executorselector.filters的配置值,并创建了一个ExecutorFilter对象,而该对象中包含了一组FactorFilter,后面我们会说明。 使用ExecutorSelector来选出一个Executor Server,具体选择的逻辑,我们可以查看ExecutorSelector.getBest()方法。 首先通过定义的CandidateFilter(它是一个抽象类,具体实现类为ExecutorFilter)进行预筛选:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1for (final K candidateInfo : candidateList) {
2  if (this.filter.filterTarget(candidateInfo, dispatchingObject)) {
3    filteredList.add(candidateInfo);
4  }
5}

上面的filter就是FactorFilter类的实例,Azkaban内部定义了如下3种:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1private static final String STATICREMAININGFLOWSIZE_FILTER_NAME = "StaticRemainingFlowSize";
2private static final String MINIMUMFREEMEMORY_FILTER_NAME = "MinimumFreeMemory";
3private static final String CPUSTATUS_FILTER_NAME = "CpuStatus";

目前3.40.0版本不支持自定义,只能使用内建实现的,如果需要增加新的FactorFilter,可以在此基础上做一个简单改造,配置使用自己定义的FactorFilter实现。FactorFilter是一个泛型类:FactorFilter<Executor, ExecutableFlow>,根据上面定义的3种指标对Executor Server进行一个预过滤,满足要求的会进行后面的比较,加入到调度WorkFlow执行的Executor Server的候选集中。 然后,通过如下方式进行比较排序,选择合适的Executor Server:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1// final work - find the best candidate from the filtered list.
2final K executor = Collections.max(filteredList, this.comparator);
3logger.debug(String.format("candidate selected %s",
4    null == executor ? "(null)" : executor.toString()));
5return executor;

这里关键的就是this.comparator,它有一个实现类ExecutorComparator,该类中给出了需要对两个Executor Server的哪些指标进行综合比较,亦即一组比较器的定义,可以看到目前考虑了4种比较器:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1private static final String NUMOFASSIGNEDFLOW_COMPARATOR_NAME = "NumberOfAssignedFlowComparator";
2private static final String MEMORY_COMPARATOR_NAME = "Memory";
3private static final String LSTDISPATCHED_COMPARATOR_NAME = "LastDispatched";
4private static final String CPUUSAGE_COMPARATOR_NAME = "CpuUsage";

通过上面代码可以看出,在选择调度一个WorkFlow到Azkaban集群中的某个Executor Server时,需要比较Executor Server的如下4个指标:

  1. 能够运行WorkFlow的剩余容量,数值越大越优先
  2. 剩余内存用量,数值越大越优先
  3. 最近分配Flow的时间,数值越大越优先
  4. CPU使用用量,数值越小越优先

基于上面4个指标,创建了4个比较器,使用FactorComparator来表示,对需要比较的一组Executor Server,使用这4个比较器进行比较,通过加权后得到一个得分值,根据该得分值选定Executor Server,核心逻辑如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1final Collection<FactorComparator<T>> comparatorList = this.factorComparatorList.values();
2for (final FactorComparator<T> comparator : comparatorList) {
3  final int result = comparator.compare(object1, object2);
4  result1 = result1 + (result > 0 ? comparator.getWeight() : 0);
5  result2 = result2 + (result < 0 ? comparator.getWeight() : 0);
6  logger.debug(String.format("[Factor: %s] compare result : %s (current score %s vs %s)",
7      comparator.getFactorName(), result, result1, result2));
8}

上面选取了待比较的两个Executor Server都不为空的情况,分别遍历每个FactorComparator进行比较,在分别对每个Executor Server的比较结果值进行累加求和,加权得到一个分数值。从一组Executor Server中,根据最终比较的分数值,分数值最大的Executor Server为最终选定的Executor Server。

获取Executor Server的运行统计信息

在Azkaban WebServer内部,会维护集群中每个Executor Server的运行状态信息,该信息的获取是在QueueProcessorThread线程中实现的,定期去更新所维护的Executor Server的运行状态信息,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1if (currentTime - lastExecutorRefreshTime > activeExecutorsRefreshWindow
2    || currentContinuousFlowProcessed >= maxContinuousFlowProcessed) {
3  // Refresh executorInfo for all activeExecutors
4  refreshExecutors();
5  lastExecutorRefreshTime = currentTime;
6  currentContinuousFlowProcessed = 0;
7}

上面refreshExecutors()方法遍历内存中维护的所有的Executor Server,调用每个Executor Server的/serverStatistics接口,拉取Executor Server的运行状态信息。 另外,Azkaban WebServer还需要能够获取到各个Executor Server上运行的WorkFlow的状态信息,可以在ExecutorManager.ExecutingManagerUpdaterThread中看到实现,代码片段如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1results =
2    ExecutorManager.this.apiGateway.callWithExecutionId(executor.getHost(),
3        executor.getPort(), ConnectorParams.UPDATE_ACTION,
4        null, null, executionIds, updateTimes);

上面调用Executor Server的/executor?action=update接口来拉取WorkFlow的状态信息,然后更新内存中维护的状态信息数据结构。其中,有些WorkFlow可能已经运行完成,需要释放资源;有些WorkFlow状态发生变更,也需要更新Azkaban WebServer端内存中维护的数据结构。

调度WorkFlow到Executor Server上执行

上面已经选定Executor Server,结合前面代码,是通过调用ExecutorManager.dispatch()方法来实现,调度WorkFlow到该选定的Executor Server上运行,代码片段如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1try {
2  this.apiGateway.callWithExecutable(exflow, choosenExecutor,
3      ConnectorParams.EXECUTE_ACTION);
4} catch (final ExecutorManagerException ex) {
5  logger.error("Rolling back executor assignment for execution id:"
6      + exflow.getExecutionId(), ex);
7  this.executorLoader.unassignExecutor(exflow.getExecutionId());
8  throw new ExecutorManagerException(ex);
9}

通过跟踪查看apiGateway.callWithExecutable()实现,可以看到,最终是调用了Executor Server端的一个REST API接口:/executor,然后带上相关的请求参数,如action=execute、execId等。

Executor Server执行WorkFlow

很显然,Azkaban WebServer调度WorkFlow后,Executor Server在ExecutorServlet中接收到对应的请求,核心方法如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1private void handleAjaxExecute(final HttpServletRequest req,
 2    final Map<String, Object> respMap, final int execId) throws ServletException {
 3  try {
 4    this.flowRunnerManager.submitFlow(execId);
 5  } catch (final ExecutorManagerException e) {
 6    e.printStackTrace();
 7    logger.error(e.getMessage(), e);
 8    respMap.put(RESPONSE_ERROR, e.getMessage());
 9  }
10}

在收到Azkaban WebServer的调度请求后,Executor Server使用内部的FlowRunnerManager来提交WorkFlow执行。在这个过程中,首先使用ExecutorLoader从数据库中读取WorkFlow对应的信息;然后使用FlowPreparer进行初始化,创建对应的数据目录等;最后创建FlowRunner来执行WorkFlow,并跟踪其执行状态。

参考内容

  • http://azkaban.github.io/azkaban/docs/latest/
  • https://github.com/azkaban/azkaban/releases/tag/3.40.0

✦ ✦ ✦ ✦ ✦ ✦ ✦ ✦

作者: Yanjun 原文:http://shiyanjun.cn/archives/1820.html


本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-06-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构师之旅 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
基于Azkaban的任务定时调度实践
Azkaban是LinkedIn开源的任务调度框架,类似于JavaEE中的JBPM和Activiti工作流框架。
洛杉矶
2019/03/04
10.1K0
azkaban3.84.4 部署
码农GT038527
2025/04/04
1580
azkaban3.84.4 部署
CentOS 7下安装azkaban详细步骤
azkaban是一个开源的任务调度系统,用于负责任务的调度运行(如数据仓库调度),用以替代linux中的crontab.
用户5766185
2019/07/08
2K0
Azkaban 任务调度系统(安装搭建)
无论是在业务开发还是在大数据开发中,脚本都是必不可少的存在,在初期我们会使用crontab来解决问题,那么当发现规模变大监控需求可视化需求的到来Crontab已经显然满足不了需求,抱着一颗解决大数据任务脚本和业务任务脚本难题的心态最终在oozie和Azkaban选择了使用Azkaban来作为公共任务调度系统,那么就随着笔者一同来学习Azkaban的基础搭建场景和基本使用吧.
喵了个咪233
2022/03/24
5930
大数据平台 —— 调度系统之Azkaban
其中AzkabanWebServer可以说是整个Azkaban工作流系统的主要管理者,它负责project管理、用户登录认证、定时执行工作流、跟踪工作流执行进度等一系列任务。
端碗吹水
2020/11/16
4.9K0
大数据平台 —— 调度系统之Azkaban
2.Azkaban 3.x 编译及部署
Azkaban 在 3.0 版本之后就不提供对应的安装包,需要自己下载源码进行编译。
每天进步一点点
2022/12/15
4870
2.Azkaban 3.x 编译及部署
Azkaban-3.x 配置信息说明
azkaban.executorselector.comparator.{ComparatorName}
CoderJed
2019/08/23
1.5K0
Azkaban教程[通俗易懂]
Azkaban是在LinkedIn上创建的用于运行Hadoop作业的批处理工作流作业调度程序。Azkaban通过工作依赖性解决订购问题,并提供易于使用的Web用户界面来维护和跟踪您的工作流程。Azkaban定义了一种KV文件格式来建立任务之间的依赖关系
全栈程序员站长
2022/11/01
1.3K0
Azkaban教程[通俗易懂]
1.Azkaban简介
一个完整的大数据分析系统,必然由很多任务单元 (如数据收集、数据清洗、数据存储、数据分析等) 组成,所有的任务单元及其之间的依赖关系组成了复杂的工作流。复杂的工作流管理涉及到很多问题:
每天进步一点点
2022/12/15
6880
1.Azkaban简介
深入理解Spark 2.1 Core (三):任务调度器的原理与源码分析
上一篇博文《深入理解Spark 2.1 Core (二):DAG调度器的实现与源码分析 》讲到了DAGScheduler.submitMissingTasks中最终调用了taskScheduler.submitTasks来提交任务。
小爷毛毛_卓寿杰
2019/02/13
9570
深入理解Spark 2.1 Core (三):任务调度器的原理与源码分析
定时调度任务器Azkaban安装
在大数据繁杂的ETL或其它数据处理过程当中,有些任务是需要定时执行的,虽然Linux自带了cron命令功能,但是仍不能满足最大的一点就是它不能提供集中式的管理和可视化的编辑。其实在大数据的生态当中已集成有个定时调度框架Oozie,只是实践下来发现其学习成本不低,布署的过程也较复杂。在尝试过其它分布工调度框架后(如阿里的宙斯Zeus),还是选择了社区较多人使用的Azkaban。
凡梦星尘
2024/11/20
1200
定时调度任务器Azkaban安装
Azkaban入门介绍与安装
本篇博客,小菌为大家带来的时候大数据组件之一的——Azkaban的介绍。
大数据梦想家
2021/01/26
8591
Azkaban入门介绍与安装
大数据调度平台Airflow(二):Airflow架构及原理
Airflow我们可以构建Workflow工作流,工作流使用DAG有向无环图来表示,DAG指定了任务之间的关系,如下图:
Lansonli
2022/03/29
7K1
大数据调度平台Airflow(二):Airflow架构及原理
快速学习-Azkaban实战
注意: 目前,Azkaban 上传的工作流文件只支持 xxx.zip 文件。zip 应包含 xxx.job 运行作业所需的文件和任何文件(文件名后缀必须以.job 结尾,否则无法识别)。作业名称在项目中必须是唯一的。
cwl_java
2020/02/18
5330
快速学习-Azkaban实战
Azkaban Two Server模式部署 原
Two Server模式就是把Azkaban和MySQL进行了分离,下面就介绍一下这种部署模式。
云飞扬
2019/03/12
2.8K0
Azkaban Two Server模式部署
                                                                            原
Azkaban分布安装部署
获取编译好的安装文件上传并解压/root/hd/azkaban-3.50.0 找到三个需要的配置文件 azkaban-db/build/distributions azkaban-web-server/build/distributions azkaban-exec-server/build/distributions distributions下就是我们需要的编译后的压缩文件 把压缩文件分别分发到对应的服务器
编程那点事
2023/02/25
4230
SpringBoot开发azkaban Java类型任务
在上篇文章手把手教你安装 azkaban 运行环境中,详细介绍了 azkaban服务的安装,现在就用SpringBoot来开发一个azkaban的调度任务,上传到web界面运行。
Java技术编程
2021/02/03
8810
工作流调度器azkaban(以及各种工作流调度器比对)
文章主要讲述了如何通过配置nginx.conf来实现反向代理和负载均衡。介绍了反向代理和负载均衡的概念,以及常见的方法和优缺点。还介绍了一种基于nginx的配置方法,并给出了详细的步骤和示例。
别先生
2018/01/02
3.4K0
工作流调度器azkaban(以及各种工作流调度器比对)
Azkaban快速入门系列(3) | 一文带你快速了解Azkaban的实战应用(建议收藏!!!)
一. 实战前的准备 1. 在executor服务器目录下执行启动命令 [bigdata@hadoop002 executor]$ bin/azkaban-executor-start.sh 2.
不温卜火
2020/10/28
1.1K0
Azkaban快速入门系列(3) | 一文带你快速了解Azkaban的实战应用(建议收藏!!!)
数据调度组件:基于Azkaban协调时序任务执行
在数据服务的业务场景中,很常见的业务流程就是日志文件经过大数据分析,再向业务输出结果数据;在该过程中会有很多任务需要执行,并且很难精准把握任务执行的结束时间,但是又希望整个任务链尽快结束释放资源。
知了一笑
2021/04/16
3910
数据调度组件:基于Azkaban协调时序任务执行
相关推荐
基于Azkaban的任务定时调度实践
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档