Skip to main content

调度属性配置

概述

什么是调度

在典型的批处理场景中,任务都是周期性的运行(例如每天运行一次),且不同的任务之间会存在上下游依赖关系,例如数据抽取任务会首先运行,之后才运行SQL处理任务。在这一过程中,周期性、任务的上下游依赖关系就是「调度」的基本概念,调度系统的职责可以归结为2方面:

  • 生成周期实例:参考实例的生成
  • 按计划运行实例:由于任务之间存在上下游关系(有些同时存在自依赖),需判断任务是否到达了运行的条件

用户可以在离线开发中进行调度属性的配置,主要包含调度周期配置、上下游依赖性、跨周期依赖、任务优先级配置等内容

基本原则

调度系统的基本原则分为以下2类:

判断任务运行条件

每天按计划运行周期实例时,调度系统判断一个实例是否可以运行,需满足2方面条件:

  • 任务的计划时间
  • 上游任务是否全部成功

若不能同时满足以上2个条件,则任务会处于等待提交状态。满足以上2个条件时,此任务在调度系统中具备了运行的条件,调度系统会将任务「提交」至计算引擎(任务进度等待运行状态),此任务还需要获得集群的计算资源,集群资源的分配由计算集群分配,用户不可干预,因此,满足时间+上下游依赖条件,并不意味着任务会立即开始运行,其可能在等待计算资源

例如,某任务A计划时间为每天02:00,上游依赖B、C、D 3个任务,那么判断A任务是否可运行,其判断逻辑为:

  • 当前时间>=02:00
  • 上游任务B、C、D是否全部为成功状态

寻找上游实例

在任务的周期性、上下游、跨周期等各种场景,尤其是不同周期的任务相互依赖,调度系统进行依赖判断的基本原则是:

tip
  • 第一条:当前实例寻找上游实例时,永远会去寻找一个与其计划时间相等,或之前的实例,不会去寻找未来时间的实例

  • 第二条:这一原则仅在如下条件下会被打破:当均为天任务时,会在当天的实例中,寻找上游任务的实例

对这一原则的场景化描述请参考几种典型场景

任务与实例

任务与实例是一对多的关系,在「数据开发」模块中配置的SQL任务、同步任务,其中包含代码、配置信息等,这是一个任务(Job),一个任务每运行一次,被称作一个实例(Instance)。任务是固定的一个配置,将一个任务运行多次,每次的结果、数据产出都不一样,在概念上进行区分是很有必要的。在本文的描述中,「任务」和「实例」可能会混用,读者需结合上下文理解其实际含义

周期性

周期粒度

在「数据开发」模块,任意打开一个任务,可在其右侧的「调度依赖」面板中,可配置「调度周期」为天、周、月、小时、分钟、cron表达式及自定义调度周期等方式。

调度周期起调时间配置
天调度任务,即每天自动运行一次。新建周期任务时,默认的时间周期为每天0点运行一次,可根据需要自行指定运行时间点,配置"具体时间": - 小时:单选下拉列表,00-23,默认选中00 - 分钟:单选下拉列表,00-59,默认选中00
周调度任务,即每周的特定几天里每天在特定时间点自动运行一次,需配置 选择时间 和 具体时间 - 选择时间:复选下拉列表{星期一;星期二;……星期日},可复选,默认选中 星期一 - 具体时间:同 调度周期-日 相同;
月调度任务,即每月指定的特定几天里每天在特定时间点自动运行一次,需配置 选择时间 和 具体时间 - 选择时间:复选下拉列表{每月最后一天;每月1号;每月2号;……每月31号},可复选,默认选中 星期一 - 具体时间:同 调度周期-日 相同;
小时小时调度任务,即每天指定的时间段内按N*1小时的时间间隔运行一次,比如每天1点到4点的时间段内,每1小时运行一次。当调度周期切换到非天级调度时,节点起调时间将不可选,需配置 开始时间 、 结束时间 和 间隔时间 - 开始时间、结束时间:同 调度周期-日 类似,小时可选择00-23,分钟不可选,开始时间的分钟为0,结束时间的分钟为59; - 间隔时间:单选下拉列表{1小时;2小时……23小时},默认选中1小时; - 开始时间,应早于结束时间 ;
分钟分钟调度任务,即每天指定的时间段内按N*指定分钟的时间间隔运行一次,目前能支持的最短时间间隔为每5分钟运行一次,当调度周期切换到非天级调度,节点起调时间将不可选,需配置 开始时间 、 结束时间 和 间隔时间 - 开始时间、结束时间:同 调度周期-小时 相同; - 间隔时间:单选下拉列表{5分钟;10分钟;……55分钟},默认选中5分钟; - 开始时间,应早于结束时间
Cron表达式填写Cron表达式
自定义调度周期选择在控制台上传的自定义调度周期
tip
  • 按照小时周期调度时,时间周期按左闭右闭原则计算,比如配置为从0点到2:59点的时间段内,每隔1个小时运行一次,表明时间区间为[00:00,02:59],间隔为1小时,调度系统将会每天生成3个实例,分别在0:00/1:00/2:00运行。
  • 离线开发支持的最小调度间隔为5分钟,不支持更短的调度周期,若存在此种场景,可考虑实时计算等其他解决方案
  • 具体时间并不表示任务的实际开始时间,系统可能会因为上游任务延迟、集群资源紧张等原因造成延迟执行

Cron表达式

Cron表达式是一个具有时间含义的字符串,字符串以5~6个空格隔开,离线仅支持6个域,格式为X X X X X X 。其中X是一个域的占位符。代表年份的域离线获取的是生效日期的年份。单个域有多个取值时,使用半角逗号,隔开取值。每个域可以是确定的取值,也可以是具有逻辑意义的特殊字符。每个域最多支持一个前导零。

说明 如指定每天上午8:15执行任务,Cron表达式可指定为0 15 8 ? * * 0 15 08 ? * * ,而不能指定为0 15 008 ? * *

自定义调度周期一

域取值

下表为Cron表达式中六个域能够取的值以及支持的特殊字符。

是否必需取值范围特殊字符
[0, 59]* , - /
分钟[0, 59]* , - /
小时[0, 23]* , - /
日期[1, 31]* , - / ? L W
月份[1, 12][JAN, DEC]* , - /
星期[1, 7][MON, SUN]。若您使用[1, 7]表达方式,1代表星期一,7代表星期日。* , - / ? L #

特殊字符

Cron表达式中的每个域都支持一定数量的特殊字符,每个特殊字符有其特殊含义。

特殊字符含义示例
*所有可能的值。在月域中,表示每个月;在星期域中,表示星期的每一天。
,列出枚举值。在分钟域中,5,20表示分别在5分钟和20分钟触发一次。
-范围。在分钟域中,5-20表示从5分钟到20分钟之间每隔一分钟触发一次。
/指定数值的增量。在分钟域中,0/15表示从第0分钟开始,每15分钟。在分钟域中3/20表示从第3分钟开始,每20分钟。
?不指定值,仅日期和星期域支持该字符。当日期或星期域其中之一被指定了值以后,为了避免冲突,需要将另一个域的值设为?。
L单词Last的首字母,表示最后一天,仅日期和星期域支持该字符。在日期域中,L表示某个月的最后一天。在星期域中,L表示一个星期的最后一天,也就是星期日(SUN)。如果在L前有具体的内容,例如,在星期域中的6L表示这个月的最后一个星期六。
W除周末以外的有效工作日,在离指定日期的最近的有效工作日触发事件。W字符寻找最近有效工作日时不会跨过当前月份,连用字符LW时表示为指定月份的最后一个工作日。在日期域中5W,如果5日是星期六,则将在最近的工作日星期五,即4日触发。如果5日是星期天,则将在最近的工作日星期一,即6日触发;如果5日在星期一到星期五中的一天,则就在5日触发。
#确定每个月第几个星期几,仅星期域支持该字符。在星期域中,4#2表示某月的第二个星期四。

取值示例

以下为Cron表达式的取值示例。

示例说明
0 0 10,14,16 * * ?每天上午10:00点、下午14:00以及下午16:00执行任务
0 0/30 9-17 * * ?每天上午09:00到下午17:00时间段内每隔半小时执行任务
0 14 * ?每天下午14:00到下午14:59时间段内每隔1分钟执行任务
0 0-5 14 * * ?每天下午14:00到下午14:05时间段内每隔1分钟执行任务
0 0/5 14 * * ?每天下午14:00到下午14:55时间段内每隔5分钟执行任务
0 0/5 14,18 * * ?每天下午14:00到下午14:55、下午18:00到下午18:55时间段内每隔5分钟执行任务
0 15 10 L * ?每月最后一日上午10:15执行任务
0 15 10 ? * 6L每月最后一个星期六上午10:15执行任务
0 15 10 ? * 6#3每月第三个星期六上午10:15执行任务
0 10,44 14 ? 3 WED每年3月的每个星期三下午14:10和14:44执行任务

自定义调度周期

当调度周期无规律且复杂时,用户可使用自定义调度周期,例如在金融客户的使用场景中,可能存在计划日期是国内外的金融交易日期,交易日期无法用cron表达式等方式表示,因此可使用自定义调度日期。

自定义调度周期配置

控制台管理员可在「控制台->全局配置->自定义调度周期」中点击「添加按钮」上传自定义调度日期,如图所示

自定义调度周期二

自定义调度周期3

按要求上传csv格式文件并填写名称,系统将解析出上传的自定义调度日期。文件模版中标明了日期上传要求,如下图

自定义调度周期4

按要求填写自定义调度周期,如下图

自定义调度周期5

上传文件,弹窗展示如下图日历,可预览文件中配置的自定义调度日期

自定义调度周期6

在弹窗中展示最后一次调度日期,若最后一次调度日期与当前日期时间间隔小于等于十天,则会在列表中变红提示。

自定义调度周期7

点击确认后,列表末尾生成新的记录

自定义调度周期8

点击「查看」按钮,可以查看自定义调度配置信息和任务使用情况,如图

自定义调度周期9

点击「编辑」按钮,可以对自定义调度周期进行下载和重新上传

自定义调度周期10

对自定义调度周期进行删除时,需要确认没有任务应用

自定义调度周期11

自定义调度周期使用

已添加的调度周期在全平台范围内生效,在任一任务的「调度依赖->调度属性」选中「自定义调度周期」,会在下方展示自定义调度周期选择框,如图所示

自定义调度周期的选择范围是所有在控制台配置的自定义调度周期,选中自定义调度日期后,可点击右侧的「预览」按钮,可以查看自定义调度周期的生效范围,如图所示

自定义调度周期13

当自定义调度周期上传模版是精确到日期时,选择该自定义调度周期,可在调度配置处设置调度时分,如下图所示

image-20220927191421746

生效日期

  • 指当前调度任务的调度生效日期范围,默认为100年,若有特殊需要可以修改此时间范围
  • 超出生效日期后,此调度任务的实例不会再生成

出错重试

勾选出错重试,当本任务运行失败时,会进行自动重试,每次间隔2分钟,可配置重试1次至5次,默认重试3次。

tip

建议对重点任务配置重试,例如如下几种场景:

  • 数据量较大的同步任务,或运行时间较长的同步任务
  • 某些重要性较高的任务
  • 某些资源消耗比较大的任务

冻结任务

如果需要让某个任务停止运行一段时间,可以在「任务开发」模块打开某任务,在右侧「调度依赖」面板中勾选「冻结」,表示此任务进入冻结状态

  • 处于冻结状态的任务,其周期实例依然会生成,但不会运行
  • 对于存在依赖关系的多个任务,如果将上游任务A冻结,则下游任务B也会进入 冻结 状态,B任务的实例也会产生,但不会运行,在B任务的执行日志中会打印出是由于A任务被冻结才没有运行的
  • 冻结是立即生效的,冻结状态的任务,生成的实例不会立即进入冻结状态,会首先进入等待提交状态,到达计划时间后,无论上游任务的状态怎样,会立即进入冻结状态,按此逻辑,若任务实例的计划时间还未到达,任务解冻后可以正常运行
  • 已经进入冻结状态的实例无法解冻,若需要这些实例执行,必须先对任务解冻,解冻后再对实例进行「重跑」
tip

对冻结状态的任务执行补数据,补数据实例会正常运行

自动跳过

由于小时/分钟任务的调度频率很高,且偶尔会存在执行时间过长的情况,为节约计算资源,让任务尽快「追赶」上当前时间,离线开发支持对小时/分钟任务配置自动跳过的逻辑

假设设置分钟任务的调度周期为10分钟一次,正常需要2分钟运行完成,且分钟任务处理的是当天全天的数据,且设置了自依赖模式,在2020-05-03,任务的计划时间点分别为:

  • 2020-05-03 23:10:00 --集群发生故障,任务在23:11分启动运行,但直到23:35才运行结束
  • 2020-05-03 23:20:00 --不运行实例,直接将其状态置为「自动取消」
  • 2020-05-03 23:30:00 --不运行实例,直接将其状态置为「自动取消」
  • 2020-05-03 23:40:00 --运行23:40的实例
  • 2020-05-03 23:50:00 --无论是否跳过,一天中的最后一个实例都会运行
  • 2020-05-04 00:00:00

如上文所述,在小时、分钟任务中,如果勾选了自动跳过,则离线开发可以自动跳过已经「过期」的实例,直接运行最新的一个,即可实现最新数据的产出,当然这对任务代码、自依赖模式也有要求

caution

自动跳过只会跳过一天中间的实例,某一天最后一个实例(上例中的23:50的实例)不会跳过,以保障当天最后一个实例产出当天全天的数据

上下游依赖

为什么要配置调度依赖

一些任务的数据加工依赖其他任务的数据产出。在离线开发中支持自动依赖、手动依赖两种依赖配置方式。

任务依赖配置

自动依赖

对于SparkSQL、HiveSQL、ImpalaSQL任务,可自动解析用户SQL代码,并自动推荐上游任务,其基本逻辑如下:

假设A任务代码:

INSERT INTO ta
SELECT * FROM t

假设B任务代码:

INSERT INTO tb
SELECT * FROM ta

应该配置A为B任务的上游,则当A任务已经提交当前提下,在B任务的「调度属性」的「任务间依赖」模块选中依赖方式为「自动依赖」按钮,将在依赖列表中显示A任务。

选择自动依赖时,会根据当前IDE的代码的血缘解析结果(通过解析create as , insert into as, insert overwrite into as等语句)把当前任务所有来源表的产出任务解析在列表中。

tip

依赖生成方式从自动依赖切换成手动依赖时,自动依赖解析得到的上游任务保留,不自动删除。

依赖生成方式从手动依赖切换成自动依赖是,手动依赖添加的任务将被全量覆盖。

手动依赖

手动依赖的添加方式可选择手动添加或依赖推荐,依赖推荐目前仅支持三种任务类型的解析:SparkSQL、HiveSQL、ImpalaSQL

上下游依赖1

若某任务B必须在任务A完成后运行,则A为B的上游任务,这种依赖关系可通过如下方式配置:在「调度依赖」面板中的「任务间依赖」模块选中依赖方式为「手动依赖」按钮,点击「添加依赖」,在弹窗中选择添加方式为「手动添加」,选择相应的租户、产品(离线开发、算法开发、智能标签)、项目,并输入上游任务的名称,在搜索的下拉结果中选择需要依赖的上游任务。

tip

是要实在一套平台内,任务可实现跨集群、租户、产品、项目实现依赖

tip

依赖属性为非必填项,当下游任务需依赖上游任务产出数据,建议配置依赖关系

tip

上游任务失败后,下游任务不会运行,且下游任务的状态会保持「等待提交」

当在弹窗中选择添加方式为「依赖推荐」时,和「自动依赖」的逻辑一致,会根据当前IDE的代码的血缘解析结果(通过解析create as , insert into as, insert overwrite into as等语句)当前任务所有来源表的产出任务将会解析在「选择任务」列表,列表中还会展示类型、项目、产品、责任人、关联内容(当前任务与上游任务的关联表,以schema.table的方式展示)等字段。选中任务后点击「确认」,可与选中任务建立上下游依赖关系。

上下游依赖2

除SparkSQL、HiveSQL、ImpalaSQL任务外,任务间依赖方式默认为「手动依赖」,且不存在「依赖推荐」。

note

当选择自动依赖时,默认会和所有血缘关系的任务建立依赖关系,无法修改。

当选中推荐依赖时,可以在所有推荐的血缘关系的任务中,选择合适的任务建立依赖关系。

跨周期依赖

基本配置

跨周期依赖比较典型的场景是:昨天的实例必须先执行成功,今天的实例才可以调度起来,跨周期依赖的选项有4种,结合实例来看,假设A任务每天01:00运行,分析3月2日、3日的实例,不同的跨周期依赖的效果如下:

  • 不依赖上一调度周期,无论2日的实例运行情况如何,3日的实例会正常运行
  • 自依赖,等待上一调度周期成功,才能继续运行,2日的实例必须运行成功,3日的实例才具备运行的条件,若2日的实例未处于成功状态,则3日的实例会处于「等待提交」的状态
  • 自依赖,等待上一调度周期结束,才能继续运行,与上一种情况类似,但不要求2日的实例必须成功,只需要2日的实例运行结束(成功、失败、取消、自动取消)即可
tip

结束状态包括成功、失败、取消、自动取消

tip

依赖属性配置的调度依赖是同周期依赖和跨周期依赖不冲突。任务A可以配置依赖属性依赖任务B,也可以配置跨周期依赖依赖B,如此任务A既依赖任务B,本周期也依赖任务B上周期。

高级配置

跨周期依赖配置中还有另外2种配置:

  • 等待下游任务的上一周期成功,才能继续运行
  • 等待下游任务的上一周期结束,才能继续运行

这2种情况使用的情况较少,主要场景是:本周期该任务是否运行,取决于下游任务上一周期的运行情况。如果下游任务的上一周期运行成功/结束,本周期的任务才能开始运行,例如:

A任务、B任务:

  • 调度周期:均为10分钟
  • A为B的上游
  • A、B的结果表是同一个,均向表t的天分区写入数据,代码如下: INSERT INTO t partition (ds = 20200303) SELECT * FROM ……
  • 当A与B任务同时运行时,会出现二者同时向同一个分区写入数据的情况(无论A、B是否配置自依赖,均会发生2个任务向同一分区写数据的情况),会造成数据错乱或任务失败,如下图所示:

yilaixiayou

在这种场景下,需要等待B任务的上个周期实例完成运行,A任务才能启动运行,应形成如下的依赖关系:

yilaixiayou2

A任务的跨周期依赖应配置为:等待下游任务的上一周期结束/成功,才能继续运行

tip

对小时、分钟任务等高频率调度的任务,建议将依赖设置为不依赖,或者等待XX结束,防止中间某个实例失败造成下游的大面积延误或失败

几种典型场景

天任务之间的依赖

假设A、B、C任务均为天任务,依赖关系为:A→B→C,3个任务的计划时间分别为:A(01:00)、B(03:00)、C(02:00)。在资源十分充足的条件下,会产生如下的运行情况:

  • A:01:00开始运行
  • B:03:00开始运行
  • C:在当天的天任务中寻找上游依赖,则判定依赖B任务03:00的实例,C任务会在B任务03:00运行结束后才具备运行条件,C可能会在03:10开始运行
tip

当均为天任务时,会在当天的实例中,寻找上游任务的实例

短依赖长

以天依赖月为例,A为月任务,B、C为天任务,依赖关系为:A→B/C

3个任务的计划时间为:

  • A:每月1日,01:00
  • B:每天,01:30
  • C:每天,03:00

下面以9月5日为例:B、C任务寻找的最近的一个A任务的实例,为9月1日 01:00(计划时间)的实例,则会形成如下图的依赖关系:

duanyilai1

假设3个任务的计划时间变更为:

  • A:每月25日,01:00
  • B:每天,01:30
  • C:每天,03:00

依然以9月5日为例:B、C任务寻找的最近的一个A任务的实例,为8月25日 01:00(计划时间)的实例,则会形成如下图的依赖关系:

duanyilai2

长依赖短

以天依赖小时为例,A为小时任务,B、C为天任务,依赖关系为:A→B/C

3个任务的计划时间为:

  • A:每天,每隔1小时运行一次,计划时间分别为:00:00、01:00……
  • B:每天,01:00
  • C:每天,03:30

依然以9月5日为例:B、C任务寻找的最近的一个A任务的实例,则会形成如下图的依赖关系:

changyilai

tip

当前实例寻找上游实例时,永远会去寻找一个与其计划时间相等,或之前的实例,不会去寻找未来时间的实例

月被依赖的特殊处理

当月任务被依赖时,会对月任务的实例做一次特殊处理,场景如下:

假设在9月5日新建了一个月任务A,计划时间是每月1日,并设置了2个天任务B、C作为A任务的下游,按上文的依赖判断原则,B、C任务应依赖于A任务9月1日的实例,但A任务5日才被创建,不存在1日的实例,这种场景下调度系统会做特殊处理:

A由于首月创建时间较晚,实例还不存在时,B、C任务依然可以运行

tip

A任务可以通过补数据来生成9月1日的实例,但实例不会在补数据实例中寻找上游,仅会在周期实例中寻找上游

实例的生成

离线开发在每天22:00统一生成第二天所有需要的任务实例,基于以上设计,任务开发时需要注意任务的提交时间,这里以一个天周期调度任务A为例:

1576481042730 42679a07 f1db 41fe 82dd 75bd64b20eb7

任务A基本信息:调度周期:1天;具体调度时间:8:00;

  1. 若在1月1日21:00提交A任务(时间轴上侧),离线开发会在当天22:00产生A任务的实例,并会在1月2日8:00第一次运行
  2. 若在1月1日23:00提交A任务(时间轴下侧),由于离线开发已经在22:00产生了1月2日的所有实例,A任务在1月2日将不会运行。A任务的实例将会在1月2日22:00产生,并在1月3日第一次运行
note

可以通过调整batch.job.graph.build.cron来更改实例生成时间,通过下图两个步骤进行修改

1、打开EM找到engine服务

2、在配置信息中找到batch.job.graph.build.cron修改时间

image-20221011172847098

image-20221011172903335

任务优先级

调度系统支持为任务手动设置优先级,在「数据开发」模块中,任务的「环境参数」中编辑优先级参数,默认参数为:

##任务优先级, 值越小,优先级越高,范围:1-1000
job.priority=10
JAVACopied!

设置了任务优先级后,可能不容易观察到效果,原因是优先级的判断是弱于任务的计划时间和上下游依赖的,只有在大量任务同时满足了计划时间+上下游依赖的前提下(即满足提交至引擎的条件),任务会大量堆积在控制台,优先级参数才会体现较为明显的效果。

caution

各种参数的优先级判断顺序:任务计划时间 > 任务上下游 > 任务优先级参数

其他

  • 任务被删除

如果此任务被其他任务依赖(是其他任务的上游任务),则此任务不能被删除,您需要先解除依赖关系再进行删除, 任务删除后,已生成的任务实例不会被删除,但会运行失败

  • 想在每月的最后一天计算当月数据怎么办

离线开发在配置任务调度时,配置的都是计划时间,通常的每月最后一天计算当月数据,都是指的是每月1日凌晨计算上个月整月数据,建议计划时间选择每月的1日运行即可