作者:杨冬 欢迎转载,也请保留这段声明。谢谢! 出处:https://andyyoung01.github.io/ 或 http://andyyoung01.16mb.com/
前一篇文章我们创建了简单的、独立的不依赖于其它任务的任务。它与我们非常熟悉的Linux系统上的Cron守护进程非常类似。Chronos也有能力创建复杂的、依赖于其它任务的任务。这个任务只有当它的父任务成功完成后才执行。这样的典型的任务包括用于数据处理和分析的ETL任务。
使用Chronos创建复杂任务 Chronos可以创建一个复杂的任务,它至少对其它任务有一个依赖(它只在它所依赖的父任务成功完成后运行)。这可以是一个类似于通过extract-transform-load (ETL)管道进行数据处理的任务,它可以每小时、每天或者每周运行一次。一个典型的ETL任务做如下的工作:
Extract提取数据。
Transform转换数据,将数据存储为更适合分析的格式。
Load装载数据,将数据保存到目标存储位置。
在Chronos里,依赖其它任务的任务的配置文件里并不包括schedule字段,而是指定一个或多个父任务(使用parents字段),父任务成功完成之后此任务才能开始运行。下图描述里一个在Chronos里的ETL任务,注意schedule和parents字段的区别: 下面我们看一个实例:这个ETL计划任务对《War and Peace》书中的单词进行统计,统计出现频率最高的20个单词。这个例子使用了Spark。它的任务依赖如下图所示: 由于本篇主要是关于Chronos的,所以Spark等的安装配置及如何编写Spark的map/reduce程序本篇不再详细说明,上图中的HDFS我们也用本地文件系统代替,这样使我们的关注点集中在Chronos这里。
如何在Mesos集群上运行Spark,请参考官方文档 。
首先编写第一个任务的JSON文件:01-download-war-and-peace.json 1
2
3
4
5
6
7
8
9
{
"name" : "download-war-and-peace" ,
"description" : "Download the text of War and Peace from Project Gutenberg." ,
"schedule" : "R1//PT1M" ,
"command" : "cd $MESOS_SANDBOX && cp 2600-0.txt /tmp/warandpeace.txt" ,
"uris" : [
"http://www.gutenberg.org/files/2600/2600-0.txt"
]
}
上面的代码清单从Project Gutenberg下载了War and Peace的文本,并将其存储到Mesos的工作目录中。在ETL任务的下一步将进行Spark的map/reduce任务,来计算文件中每个单词的出现次数。下面的代码清单创建了第二个Chronos任务,这次在parents
字段中指定了前一个任务(download-war-and-peace)。02-spark-wordcount-job.json 1
2
3
4
5
6
7
8
9
10
11
12
{
"name" : "war-and-peace-wordcount-spark-job" ,
"description" : "Use Spark to count all the words in War and Peace" ,
"parents" : ["download-war-and-peace" ],
"command" : "/opt/spark-2.0.0-bin-hadoop2.7/bin/spark-submit spark-wordcount-master/war-and-peace-wordcount_2.10-0.1.1-SNAPSHOT.jar ${basepath}" ,
"uris" : [
"https://github.com/andyyoung01/spark-wordcount/archive/master.zip"
],
"environmentVariables" : [
{ "name" : "basepath" , "value" : "/tmp" }
]
}
上面的代码清单从github下载打包好的jar文件,并从工作目录中读取上一步下载好的文本文件。为了在Mesos UI中将结果显示出来,在下一步读取Spark的统计结果,排序,并且取得前20行。类似于上面的步骤,这里也指定了parents
字段来确定此任务对前一任务的依赖。03-load-results-job.json 1
2
3
4
5
6
7
8
9
{
"name" : "load-war-and-peace-word-counts" ,
"description" : "Read the output from HDFS and send it to stdout" ,
"parents" : ["war-and-peace-wordcount-spark-job" ],
"command" : "cat ${basepath}/result/part-* | sort -t, -rnk2 | head -20" ,
"environmentVariables" : [
{ "name" : "basepath" , "value" : "/tmp" }
]
}
好了。上面三个任务运行了一个ETL管道,它统计了War and Peace里出现频率最高的20个单词。下面的脚本文件可以批量将三个任务提交到Chronos里:create-jobs.sh 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash
if [[ ! $# > 0 ]]; then
echo "Usage: $0 <http://chronos-host:4400>"
echo
exit 1
else
CHRONOS_URL=$1
fi
DIR=$(dirname "${BASH_SOURCE} " )
CURL=""
for job in "${DIR} " /*.json; do
echo -n "Creating job ${job} in Chronos..."
if grep \"schedule\" " ${job} " > /dev/null; then
curl -H 'Content-Type: application/json' -d @${job} ${CHRONOS_URL} /scheduler/iso8601
[[ $? == 0 ]] && echo "Done." || echo " Error!"
elif grep \"parents\" "${job} " > /dev/null; then
curl -H 'Content-Type: application/json' -d @${job} ${CHRONOS_URL} /scheduler/dependency
[[ $? == 0 ]] && echo "Done." || echo " Error!"
else
echo "Error: could not determine job type for '${job}' "
fi
done
将上面创建的3个json文档放在当前目录下,并确保目录中没有其它的json文件。然后使用如下命令调用上述脚本:
$ create-jobs.sh http://your-chronos-ip:4400
查看任务状态 在运行了上述命令后,可以在Chronos的web界面中查看任务的运行状态及依赖关系: 在Mesos的界面中也可以查看任务的状态,如下图: 上图点击Sandbox进入该任务的工作目录后,可以继续查看任务的stdout: 最后显示出Spark的运行结果,统计出该书中出现频率最高的20个单词:
本文旨在学习Chronos的复杂任部署,文中对于Spark进行了简化的部署,省略了HDFS的部署,关于Spark及HDFS的部署请参考官方文档。