使用PyODPS节点监测SDK上传数据的完成节点

一、前言

一直以来公司都有个痛点亟待解决。分库分表的MongoDB上传数据至ODPS,于是就有了一套利用tunnel java sdk上传数据的服务。但是上传完数据后DataWorks上的任务链依赖如何开始传递,一直没有解决。
老办法是打时间差,按照一般上传耗时3个小时计算,所有任务的起点都配置在凌晨4点开始,这在大多数时候都能生效,但在一些流量特别大的日子就会异常,数据没传完,但任务已经开始执行了,导致执行的结果都是错的。
所以,需要有个任务能够嗅探数据已经传输完毕,后续的任务都依赖这个嗅探任务。

二、解决方案

首先,新增一张表用作监控。

CREATE TABLE `one_day_monitor` (
	`flag` BIGINT
)
PARTITIONED BY (
	pt STRING COMMENT 'yyyymmdd'
)
LIFECYCLE 37000;

在正常传输完整数据后,在这张监控表里写一条记录,令当天分区的flag = 1。之后的操作就围绕这个1来进行。


终于来到标题内容,创建一个PyODPS节点,过程不赘述了。
先贴代码:

import time
t = o.get_table('one_day_monitor',project='xxxxx')
pptt = 'pt={}'.format(args['bizdate'])

end_flag = 1  ##结束标记
th = 1  ##时间标记,小时维度
while end_flag and th < 8:
    reader = t.open_reader(partition=pptt)
    f = reader[0].flag
    if f == 1:
        end_flag = 0
    else:
	    time.sleep(600)
	    lt = time.localtime(time.time())
	    th = lt.tm_hour

if th >= 8:  ##如果运行到8点则直接终止该任务
    exit('超时结束')
else:
    print '正常结束'

简单解释下,

  1. args['bizdate'] 是PyODPS的参数调用方式,详情可见我上一篇博文或阿里云官方文档;
  2. end_flag 标记取到监控表的flag是否为1,用于退出循环;
  3. 退出循环条件之二是一个时间参数,利用time模块取到当前的小时数,如果超过8点则退出,并在后续的条件判断力报错,用于任务失败;

三、纠错

本以为结束了,测试通过——安心提交——打包发布,等待明天的任务调度。
一早来看,竟然失败了,遂查看任务运行日志,发现任务开始执行时,one_day_monitor表没有当日分区,当日分区是SDK数据上传时创建的,任务开始执行时找不到该分区导致报错。测试时是下午,当时分区数据已经存在,所以没有发现这个bug,于是调整思路微调下脚本。


既然取记录时分区有可能还未创建,那么只要分区创建了不就代表数据已经传输完成么。于是从判断字段flag是否为1,转变为判断是否存在分区即可,代码见下:

import time
t = o.get_table('yp_one_day_monitor',project='devops')
pptt = 'pt={}'.format(args['bizdate'])

end_flag = 1
th = 1
while end_flag and th < 8:
    if t.exist_partition(pptt):  ##判断是否存在分区
        end_flag = 0
        print '取到分区啦'
    else:
        time.sleep(600)
        lt = time.localtime(time.time())
        th = lt.tm_hour

if th >= 8:  ##如果运行到8点则直接终止该任务
    exit('超时退出!')
else:
    print '正常结束'

四、结语

虽然Python老早就会写,但是在ODPS上使用Pyhton来解决问题还是第一次。使用这种高级语言可以完成很多单纯SQL没法完成的骚操作,接下来也会继续深入体验阿里云的PyODPS。
如果读者有跟我相似的工作上的困扰,除了搬运文中代码外,SHELL节点理应也能完成类似的功能,敬请自行体验啦。


五、补充 —— 极度疑似一个阿里云的BUG

后来又发现了新的问题,采用自定义参数args['bizdate']时,节点点击运行(F8)运行正常,但是在运维中心的调度实例均报错,参数没有被正确调用。
改为系统参数的调用方式后,结果相反,在节点的运行异常,但是周期实例、测试实例、补数据实例均能正确执行。
这。。。我目测应该是阿里云的BUG,如果有读者知道详情的,诚挚请教。

你可能感兴趣的:(python,大数据,ODPS,Python)