监控框架中关键步骤的处理策略大型的应用系统往往比上面说的情况复杂,例如多 Job 同时运行并且处于不同的状态;每个 Job 启动后资源的调度竞争使得运行状态不一定持续稳定;服务器稳定性、网络稳定性都会对监控系统的鲁棒性提出要求和挑战。因此,如何处理众多的非功能性问题就成为考量监控框架稳定性的重要指标。
多 Job 并发管理思路
实际的应用系统中 Job 往往是并发的,怎样既能同时监控多个 Job 的状态,又不增加框架的复杂性呢?这里要有一个很好的处理方式才能达到平衡。我们注意到通常返回的 JSON 文件中有"runId"这一项,这是在 Job 创建时服务器端赋予 Job 的唯一标识符,所以可以利用这一项作为区分不同 Job 的标记。我们使用如下的方式:将第一次返回的 JSON 文件进行解析,然后保存 runId 项。在后续持续监控时,只需获取相应 runId 项的状态(status)。由此,我们只需要把 CheckStatus 方法中的实现按照如下方法,加以改造:
清单 4. runId 状态获取1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| sub1=`cat $outputPath/tempJobID.txt |sed 's/\"//g' | grep runId`
JobRunId=$(echo $sub1| cut -f 2 -d :| cut -f 1 -d ,| cut -f 2 -d " ")
CheckStatus(){
JobStatus="JobStarting..."
until [ $JobStatus = "Succeeded" ] || [ $JobStatus = "Failed" ]
do
echo "Job Current Status is $JobStatus"
sleep 5
curl -k -X POST -H "$session" -H 'Cache-Control: no-cache' -H
'Content-Type: application/json'
$RequestURL/status/$JobRunId -d "{\"args\": []}"|
python -m json.tool >$outputPath/tempJobstatus.txt
sub2=`cat $outputPath/tempJobstatus.txt |sed 's/\"//g' | grep result`
JobStatus=$(echo $sub2| cut -f 4 -d :| cut -f 1 -d ,)
done
report="Job Final Status is $JobStatus"
echo $report
echo $report >> $outputPath/Report.txt
}
|
实例:若对上文的 JSON 文件运行此方法,用户可以解析出此时的 JobRunId 为"1536906964-990",在此后的 CheckStatus()方法中仅仅会去获取此 ID 的 Job 的状态。首先拿到的状态同样为"Waiting"。
交互延迟时策略及分析延迟往往发生在 Job 启动时期。如果监控系统没有考虑到与系统交互时可能产生的时延,那么返回的 JSON 文件中就不会包含完整的 Job info,因此需要一个有效且代价较小的方式,那就是适时的添加一些 sleep()。
服务器稳定性差时策略及分析运行时服务器稳定性直接影响着整个系统的反应速度,同时加载在其上的监控系统更是对服务器稳定性有着强依赖。如何结合这样的强相关性、强依赖性,并且在服务器网络稳定性不高的运行环境中稳定地监控 Job 状态呢?我们采用了一种循环等待的方式。
简单来说,就是在服务器端没有返回正确响应的时候,由监控系统发出一次 sleep() 指令,之后重新再发起一次 post 请求获取 Job 状态,若仍然无法得到返回值,则加倍 sleep()的时常,之后发起第三次 post 请求。如果三次请求均失败,则认为该项 Job 启动失败。具体的实现可以用以下方式:
清单 5. 持续监控 Job 状态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
27
28
29
| parse_json(){
sub1=`cat $outputPath/tempJobID.txt |sed 's/\"//g' | grep runId`
JobRunId=$(echo $sub1| cut -f 2 -d :| cut -f 1 -d ,| cut -f 2 -d " ")
echo $JobRunId
if [ "$JobRunId"x = ""x ];then
j=3
for ((i=1; i<=j; i++))
do
stop=$[$i*5]
echo "Job not evoked, sleep $stop s' and try again"
sleep $stop
evokeJob
sub1=`cat $outputPath/tempJobID.txt |sed 's/\"//g' | grep runId`
JobRunId=$(echo $sub1| cut -f 2 -d :| cut -f 1 -d ,| cut -f 2 -d " ")
echo $JobRunId
if [ "$JobRunId"x != ""x ];then
break
fi
done
if [ "$JobRunId"x = ""x ];then
report="Job cannot start 3 times!"
echo $report >> $outputPath/Report.txt
else
CheckStatus
fi
else
CheckStatus
fi
}
|
实例:在最差情况下,一个 Job 将会启动三次,若最终也没有能启动成功则会有如下的 report 输出:
Job not evoked, sleep 5 s' and try again
Job not evoked, sleep 10 s' and try again
Job not evoked, sleep 15 s' and try again
Job cannot start 3 times!
经过循环处理,基本上涵盖了可能出现的运行问题。一个完整的 Job 监控框架如下,通过调用以上几个 method 就可以获得:
清单 6. Job 监控框架1
2
3
4
| executeJob(){
evokeJob
parse_json
}
|
结束语RESTful 协议为服务器客户端应用开创了一个完整丰富的解决平台。运行其上的众多 Job,可以通过统一的调用接口,获取管理监控所需的一切状态信息,使得简单实现成为可能。同时在功能之上还可以并行监控,容错率高的系统将会更可靠,并能广泛地应用到实际工作中。本文通过浅显易懂的方式构建了一个轻量级的基于 RESTful API 下 Job 监控管理的框架,对现实应用中可能会出现的交互延迟、服务器端不稳定做出相应调整,大大提高了框架的鲁棒性。 |