1. 引言

众所周知,Oozie(1, 2)是基于时间条件与数据生成来做工作流调度的,但是Oozie的数据触发条件只支持HDFS路径,故而面临着这样的问题:

  • 无法判断Hive partition是否已存在;
  • 无法判断Elasticsearch index是否已写入完成;
  • ...

因此,灵活可扩展的工作流引擎才是正确姿势!下面,我将介绍如何用Crontab来打造一个类似于Oozie的简易工作流引擎;对标Oozie,其应满足功能:

  • 时间条件与数据生成触发任务,如Oozie coordinator的datasetsinput-events
  • 支持触发条件的轮询;
  • 支持任务并行执行,如Oozie workflow的forkjoin
  • 捕获错误及运行状态日志。

2. 实现

触发条件

判断Hive partition是否已存在,思路比较简单——show partitions <tb_name>后能否grep到该partition:

# check wheter $1's partition ($2) exists
hive_partition_exists() {
table_name=$1
partition=$2
hive -e "show partitions ${table_name}" | grep ${partition}
[ $? == 0 ]
}

获取Hive 表的最后一个partition,grep命令配合正则表达式中的Lookahead匹配:

# get latest hive partition
latest_hive_partition() {
table_name=$1
partition_name=$2
hive -e "show partitions ${table_name}" | tail -1 | grep -Po "(?<=${partition_name}=).*"
}

在检查ES index是否写入完成时,可用思路——定时flush index,然后判断当前时刻的doc数较上一时刻是否发生变化;若变化,则说明正在写入。Shell脚本处理json太蛋疼了,故不给出代码啦。

条件轮询

所谓“条件轮询”,是指如果数据未生成,则会一直轮询该条件是否满足。我们采用while循环中sleep的方式来实现条件轮询:

hive_partition_exists etl.ad_tb1 ${log_partition}
ad1_exists=$?
hive_partition_exists etl.ad_tb2 ${log_partition}
ad2_exists=$?
while (( ${ad1_exists} != 0 || ${ad2_exists} != 0))
do
echo "`date -d "now"`: log partitions ${log_partition} not exist, and waiting" >> ${log_path}
sleep 1m
hive_partition_exists etl.ad_tb1 ${log_partition}
ad1_exists=$?
hive_partition_exists etl.ad_tb2 ${log_partition}
ad2_exists=$?
done

实例

接下来,以Hive写Elasticsearch的为例,说明如何用crontab做定时Hive任务。hiveql脚本如下:

add jar /path/to/jars/elasticsearch-hadoop-2.3.1.jar;
set mapred.job.name=ad_tag-${LOG_PARTITION}~~${TAG_PARTITION};
set hive.map.aggr = false; insert overwrite table ad_tag
select media, a.dvc as dvc, case when c1_arr is null then array('empty') else c1_arr end as c1_arr, '${LOG_PARTITION}' as week_time
from (
select dvc, app_name as media
from ad_log
where is_exposure = '1' and day_time between date_sub('${LOG_PARTITION}', 6) and '${LOG_PARTITION}'
group by dvc, app_name
) a
left outer join (
select dvc, collect_set(c1) as c1_arr
from tag
lateral view inline(tag) in_tb
where day_time = '${TAG_PARTITION}'
group by dvc
) b
on a.dvc = b.dvc;

为了实现任务的并行执行,我用到Linux命令中的&

log_partition=`date -d "5 day ago" "+%Y-%m-%d"`
tag_partition=$(latest_hive_partition tag.dmp_tag day_time)
log_path="${log_partition}.log" echo "`date -d "now"`: log partitions ${log_partition} exist" >> ${log_path}
echo "`date -d "now"`: latest tag partition ${tag_partition}" >> ${log_path}
hive -f ad_tag1.hql --hivevar LOG_PARTITION=${log_partition} --hivevar TAG_PARTITION=${tag_partition} & hive -f ad_tag2.hql --hivevar LOG_PARTITION=${log_partition} --hivevar TAG_PARTITION=${tag_partition} exit 1

PS: 当手动执行脚本是OK的,但是crontab去执行时却出错,最可能的原因是crontab未能正确加载用户的环境变量;故可以在运行脚本中加入:

source /etc/profile
source /path/to/.bashrc

但是,用crontab做工作流调度,会存在如下问题:

  • 无法很好地管理任务之间的依赖关系;
  • 无法更好地监控任务的运行状况;
  • 因Shell脚本的编程处理能力的限制,无法更自由地做扩展。

用Crontab打造简易工作流引擎的更多相关文章

  1. 我的微型工作流引擎-功能解析及API设计

    一.前言 上一篇我给大家介绍了我的工作流的模型和基本的设计,这篇我想详细说明下我这款工作流的功能及使用示例.这款工作流主要是面向开发者设计的,为了先让大家有个全局的认识,局部功能的设计实现就不细说了, ...

  2. Winform开发框架之简易工作流设计

    一讲到工作流,很多人第一反应就是这个东西很深奥,有时候又觉得离我们较为遥远,确实完善的工作流设计很多方面,而正是由于需要兼顾很多方面,一般通用的工作流都难做到尽善尽美.微软也提供了几个版本的WF框架支 ...

  3. 《程序猿闭门造车》之NBPM工作流引擎 - 项目整体架构

    前言: 又是一年一度的圣诞节,可这关我什么事呢 :( ,好不容易周末了,还是说说NBPM吧,前不久我发布了一篇关于工作流的文章:<程序猿闭门造车>之NBPM工作流引擎 - 开篇,很多爱好工 ...

  4. Winform开发框架之简易工作流设计(转自 伍华聪博客)

    Winform开发框架之简易工作流设计 一讲到工作流,很多人第一反应就是这个东西很深奥,有时候又觉得离我们较为遥远,确实完善的工作流设计很多方面,而正是由于需要兼顾很多方面,一般通用的工作流都难做到尽 ...

  5. 工作流引擎Activiti与SpringBoot2整合--开源软件诞生17

    开源ERP技术整合系列--第17篇 用日志记录"开源软件"的诞生 [点亮星标]----祈盼着一个鼓励 博主开源地址: 码云:https://gitee.com/redragon/r ...

  6. 工作流引擎Oozie(一):workflow

    1. Oozie简介 Yahoo开发工作流引擎Oozie(驭象者),用于管理Hadoop任务(支持MapReduce.Spark.Pig.Hive),把这些任务以DAG(有向无环图)方式串接起来.Oo ...

  7. 【2016-11-7】【坚持学习】【Day22】【工作流引擎设计--执行用户】

    最近在做一个工作流引擎,架构师已经设计好了,但是我发现他设计 每一步的用户集合的设计,有一定的不足,或者是不方便,不同的组织架构影响着他的用户数据源配置方式. 于是我想花点时间去看看人家优秀是工作流引 ...

  8. .net之工作流工程展示及代码分享(二)工作流引擎

    在介绍完表单类的时候,接下来介绍工作流引擎,主要由四个类组成,分别是流程.流程步骤.流程实例.流程步骤实例类. 流程类: [Serializable] public class Flow { [Xml ...

  9. F2工作流引擎之-纯JS Web在线可拖拽的流程设计器(八)

          Web纯JS流程设计器无需编程,完全是通过鼠标拖.拉.拽的方式来完成,支持串行.并行.分支.异或分支.M取N路分支.会签.聚合.多重聚合.退回.传阅.转交,都可以非常方便快捷地实现,管理员 ...

随机推荐

  1. docker for mac 学习记录

    docker基本命令 docker run -d -p 80:80 --name webserver nginx 运行容器并起别名 docker ps 展示目前启动的容器 docker ps -a 展 ...

  2. DataTable 转换成 Json的3种方法

    在web开发中,我们可能会有这样的需求,为了便于前台的JS的处理,我们需要将查询出的数据源格式比如:List<T>.DataTable转换为Json格式.特别在使用Extjs框架的时候,A ...

  3. EF6 对多个数据库,多个DBContext的情况 进行迁移的方法。

    参见: http://stackoverflow.com/questions/21537558/multiple-db-contexts-in-the-same-db-and-application- ...

  4. python基础

    内容概要: 一.python2 or python3 目前大多使用python2.7,随着时间的推移,python3将会成为python爱好者的主流. python2和3区别: 1.PRINT IS ...

  5. FineBI:一个简单易用的自助BI工具

    过去,有关企业数据分析的重担都压在IT部门,传统BI分析更多面向的是具有IT背景的人员.但随着业务分析需求的增加,很多公司都希望为业务用户提供自助分析服务,将分析工作落实到业务人员手中.但同时,分析工 ...

  6. Angular2 Hello World 之 2.0

    最近angular2正式版发布了,现在就趁热接着记录一下2.0版的Hello World.据说由RC6升级到2.0代码改动不是很大,在写的时候也感觉改动不是很大,这次记录还是以asp.net core ...

  7. Kotlin中变量不同于Java: var 对val(KAD 02)

    原文标题:Variables in Kotlin, differences with Java. var vs val (KAD 02) 作者:Antonio Leiva 时间:Nov 28, 201 ...

  8. firebug不能加载JS文件 ,无法进行JS脚本调试

    提示: 本页面不包含 Javascript 如果 <script> 标签有 "type" 属性,其值应为 "text/javascript" 或者& ...

  9. linux压力测试工具stress

    最近给PASS平台添加autoscaling的功能,根据服务器的负载情况autoscaling,为了测试这项功能用到了stress这个压力测试工具,这个工具相当好用了.具体安装方式就不说了.记录下这个 ...

  10. Windows10-UWP中设备序列显示不同XAML的三种方式[3]

    阅读目录: 概述 DeviceFamily-Type文件夹 DeviceFamily-Type扩展 InitializeComponent重载 结论 概述 Windows10-UWP(Universa ...