使用腾讯云无服务器云函数(SCF)分析天气数据
无服务器云函数(SCF)是腾讯云提供的Serverless执行环境,也是国内首款FaaS(Function as a Service,函数即服务) 产品。其核心理念是让用户将重心放在业务的逻辑实现上,而不用关心底层的运维包括服务器、存储、网络、自动扩缩容、负载均衡、代码部署等问题。
作者:李想
无服务器云函数(SCF)是腾讯云提供的Serverless执行环境,也是国内首款FaaS(Function as a Service,函数即服务) 产品。其核心理念是让用户将重心放在业务的逻辑实现上,而不用关心底层的运维包括服务器、存储、网络、自动扩缩容、负载均衡、代码部署等问题。
云函数既然以函数这两个字来命名,其应用场景也是跟函数是极为相似的,即对一段数据执行函数计算然后进行输出。腾讯云云函数提供了各类触发器来控制函数的执行条件,代码完全由事件触发,平台根据请求自动平行调整服务资源,所以SCF特别适合需要在某些情景下需要进行数据处理的场合。例如用户上传文件之后过滤是否有违规字段,或者用户上传视频文件之后进行转码等。
腾讯云的SCF底层也是基于容器进行构建,用户的代码会加载到容器内进行执行,所以效率和性能方面能够得到保证。同时使用VPC和Unix Socket来隔离用户环境与管理环境,保证了SCF使用的安全性。函数可自动在每个地域中随机地选择可用区来运行,免除单可用区运行的故障风险。根据事件请求数量,云函数将自动横向扩容/缩容,无需用户自行配置扩缩容条件,扩容数量理论上没有上限。
提到云函数SCF也顺便提一下腾讯云将要推出的另外一个产品–批量计算。从本质上来讲批量计算和云函数都是将业务逻辑代码进行抽象而提供统一的入口供用户使用,但是两者在使用场景上也有一些区别。批量计算主要是为了处理大数据而设计的,其最关键的技术是可以对原始数据进行分片而将分片的数据分配到不同的节点进行处理,而云函数本身尽管可以并发执行,但是其处理的一般为流数据,数据量相对较小,耗时也相对较短。举个例子,如果我们需要对用户上传的文件进行实时处理,建议使用云函数SCF,而如果需要将硬盘上现有的比如几个T的用户数据进行处理,建议使用批量计算进行分批处理。
我们就以一个真实的数据来把玩一下腾讯云无服务器云函数,让大家能更好的理解云函数。数据来源于美国NCDC的天气数据:ftp://ftp.ncdc.noaa.gov/pub/data/noaa/isd-lite/
里面记录了从1900年至今所有监控点每天的监控数据,我们以2017年的数据为例(ftp://ftp.ncdc.noaa.gov/pub/data/noaa/isd-lite/2017/),里面的每一个.gz文件代表一个监控点全年的监控数据。
010010-99999-2017.gz 解压之后的文件内容如下:
2017 01 01 22 -48 -97 10205 340 60 -9999 -9999 -9999
2017 01 01 23 -47 -99 10202 346 55 -9999 -9999 -9999
2017 01 02 00 -49 -93 10190 330 90 6 -9999 4
2017 01 02 01 -47 -96 10190 346 72 -9999 -9999 -9999
2017 01 02 02 -50 -98 10189 320 40 -9999 -9999 -9999
2017 01 02 03 -47 -95 10185 328 30 -9999 -9999 -9999
2017 01 02 04 -52 -95 10176 320 20 -9999 -9999 -9999
2017 01 02 05 -62 -97 10163 310 20 -9999 -9999 -9999
2017 01 02 06 -57 -91 10150 260 20 8 -9999 -9999
2017 01 02 07 -46 -86 10141 230 30 -9999 -9999 -9999
2017 01 02 08 -37 -72 10131 206 45 -9999 -9999 -9999 …..
NCDC官方也给出了文件格式说明,1-13位记录的是观测时间,14-19位记录了观测的温度(以10倍的摄氏度进行记录)。
Field 1: Pos 1-4, Length 4: Observation Year Year of observation,
rounded to nearest whole hourField 2: Pos 6-7, Length 2: Observation Month Month of observation,
rounded to nearest whole hourField 3: Pos 9-11, Length 2: Observation Day Day of observation,
rounded to nearest whole hourField 4: Pos 12-13, Length 2: Observation Hour Hour of observation,
rounded to nearest whole hourField 5: Pos 14-19, Length 6: Air Temperature The temperature of the
air UNITS: Degrees Celsius SCALING FACTOR: 10 MISSING VALUE: -9999Field
6: Pos 20-24, Length 6: Dew Point Temperature The temperature to
which a given parcel of air must be cooled at constant pressure and
water vapor content in order for saturation to occur. UNITS: Degrees
Celsius SCALING FACTOR: 10 MISSING VALUE: -9999
假设我们有这样一个需求:每当我们上传一个观测点的数据gz文件,我们需要统计出该观测点的最高温度,并且在输出中要同时记录该观测点的站点代码(从文件名获取)。
首先我们在腾讯云COS对象存储上新建两个bucket,fredtest bucket用来上传源数据文件,output bucket用来生成输出文件。
存储桶列表
如果需要模拟批量上传,可以参考下面的Python脚本,其本质就是通过FTP拉取数据然后上传到COS。
https://github.com/xianl/SCF/blob/master/download.py
下面来编写具体的实现函数,主要需要完成下面几件事情。
- 1.上传文件后函数触发,获取上传文件的路径
- 2.调用COS SDK下载该文件,保存到/tmp目录
- 3.解压文件,读出数据内容
- 4.处理数据,计算出温度最大值
- 5.将监控点代号以及计算出来的温度最大值除以10保存到/tmp目录
- 6.将最终结果上传到COS output bucket。
核心部分的代码实现如下,完整代码可参考https://github.com/xianl/SCF/blob/master/action.py。
需要了解的是,main_handler的event参数将传入所上传文件的信息,其本质是一个json文件,例如event\’Records\’\’cos\’\’name\’可以拿到bucket信息。
def action_handler(event, context): #Create CosClient to upload/download COS file appid = 1253142785 # change to user\'s appid secret_id = u\'xxx\' # change to user\'s secret_id secret_key = u\'xxx\' # change to user\'s secret_key region = u\'sh\' # change to user\'s region cos_client = CosClient(appid, secret_id, secret_key, region) #specify the source and destination bucket location source_bucket = event[\'Records\'][0][\'cos\'][\'cosBucket\'][\'name\'] source_bucket_file_key = \'/\' + event[\'Records\'][0][\'cos\'][\'cosObject\'][\'key\'].split(\'/\')[-1] source_file_name = source_bucket_file_key.split(\'/\')[-1].split(\'.\')[0] dest_bucket = u\'output\' dest_bucket_file_key = u\'/max_temperature_\'+ source_file_name #specify the temp file location source_file_tmp_path = u\'/tmp/\' + source_file_name dest_file_temp_path = u\'/tmp/max_temperature_\' + source_file_name #download the source file from cos bucket and take actions download_ret = download_file(cos_client,source_bucket,source_bucket_file_key,source_file_tmp_path) if download_ret == 0: dest_file_temp = open(dest_file_temp_path, \'w\') max_temp = -999.9 #find the maximum temperature with gzip.open(source_file_tmp_path) as inputfile: for line in inputfile: temp = int(line[14:19]) / 10.0 if temp > max_temp: max_temp = temp #write the result to the temp file and upload to the cos bucket dest_file_temp.write(source_file_name + \' \' + str(max_temp)) dest_file_temp.close() upload_ret = upload_file(cos_client, dest_bucket, dest_bucket_file_key, dest_file_temp_path) return upload_ret else: return -1
在COS的同一个区域建立SCF云函数,执行方法为SCF的函数入口,设置为index.main_handler, 同时在代码框内贴入代码。
无服务器函数代码
第三步需要选择触发方式为COS触发,并选择COS bucket为fredtest。
设置触发方式
在fredtest bucket上传010010-99999-2017.gz文件之后,查看SCF的日志可以看到函数被正常触发了。
无服务器函数日志
output bucket同时会按照代码逻辑生成max_temperature_010010-99999-2017 文件
输出文件
文件内容为站点代码以及最后计算出的最大温度14.3℃,满足预期需求。至此,一个简单的SCF实际数据应用场景的demo就跑完了。
计算结果
总结
可以看到腾讯云SCF非常适用这种单入单出的数据处理场景,业务人员只需编写代码并在界面上进行简单的配置即可实现业务逻辑,而其所需接触的对象仅仅是例如对象存储,Message Queue,数据库等应用层对象而完全不需关心服务器,网络等基础资源,简化了很大一部分人为操作。如果能够再结合API Gateway等产品,也能够做到各个系统的业务解耦以及迭代开发。
另外,至于前文提到的批量计算,目前腾讯云还处于内测阶段,等公测之后我还会写一篇文章利用2017年的上万各监测点的数据使用批量计算来计算出2017年整年的最高温度,尽请期待。