当前位置: 首页 > Web前端 > HTML

无服务器工程实践-Serverless应用优化调试的秘密

时间:2023-04-02 13:48:00 HTML

简介:本文将以阿里云函数计算为例,提供在线调试、本地调试等多种应用优化调试解决方案。作者|刘宇前言:本文将以阿里云函数计算为例,提供在线调试、本地调试等多种应用优化调试解决方案。Serverless应用调试技巧在应用开发过程中,或者当应用开发完成,执行结果不符合预期时,我们需要进行一定的调试工作。但是在serverless架构下,调试往往会受到很大的环境限制。有时开发的应用程序在本地可以正常运行,但在FaaS平台上会出现一些不可预知的问题。而且在一些特殊的环境下,没有办法在本地模拟线上环境,给项目的开发和调试带来困难。Serverless应用的调试一直饱受诟病,但各家云厂商并没有放弃在调试方向上的深入探索。以阿里云函数计算为例,提供在线调试、本地调试等多种调试方案。在线调试1.简单调试所谓简单调试就是在控制台上进行调试。以阿里云函数计算为例,它可以通过控制台的“执行”按钮进行基本调试,如图。功能在线简单调试页面需要的时候,我们也可以通过设置Event来模拟一些事件,如图。通过设置Event来模拟事件在线调试的好处是可以使用一些在线环境进行代码测试。当线上环境有VPC等资源时,在本地环境调试起来比较困难。比如需要通过VPC访问数据库,或者有对象存储触发器的业务逻辑等。2.断点调试除了简单的调试,一些云厂商也支持断点调试,比如远程调试阿里云Function计算、腾讯云云函数的远程调试等。以阿里云函数计算的远程调试为例,可以通过控制台对函数进行在线调试。函数创建完成后,用户可以选择远程调试,点击“启用调试”按钮,如图。功能在线断点调试页面(1)启用调试后,稍等片刻,系统会进入远程调试界面,如图。功能在线断点调试页面(2)此时可以进行一些断点调试,如图。功能在线断点调试页面(三)本地调试1.命令行工具就目前来看,大部分FaaS平台都会为用户提供比较完善的命令行工具,包括AWS的SAMCLI、阿里云的Funcraft,以及一些开源的ServerlessFramework和ServerlessDevs等项目支持多云供应商。通过命令行工具调试代码的方法非常简单。以ServerlessDevs为例,在本地调试阿里云函数计算。首先确保你本地有一个函数计算项目,如图。然后本地的函数计算工程在工程下执行调试指令,比如在Docker中调试,如图。命令行工具调试函数计算二、编辑器插件以VScode插件为例。下载阿里云函数计算的VSCode插件并配置好账户信息后,就可以在本地新建一个函数,点击后就可以进行断点调试了,如图。VSCode插件调试函数计算当函数调试完成后,进行部署等操作。其他调试方案1.Web框架本地调试在阿里云FaaS平台上开发一个传统的Web框架,以Python编写的Bottle框架为例,可以添加如下代码:app=bottle.default_app()andrestrict运行方法(if__name__=='__main__'):if__name__=='__main__':bottle.run(host='localhost',port=8080,debug=True)eg:#index.pyimportbottle@bottle.route('/hello/')defindex(name):return"Helloworld"app=bottle.default_app()if__name__=='__main__':bottle.run(host='localhost',port=8080,debug=True)在线部署应用时,只需要在入口方法处填写index.app即可实现顺利部署。2.本地模拟事件调试对于非web框架,我们可以在本地构建一个方法,例如调试对象存储触发器:importjsondefhandler(event,context):print(event)deftest():event={"事件“:[{“事件名称”:“ObjectCreated:PutObject”,“事件源”:“acs:oss”,“事件时间”:“2017-04-21T12:46:37.000Z”,“事件版本”:“1.0”,"oss":{"bucket":{"arn":"acs:oss:cn-shanghai:123456789:bucketname","name":"testbucket","ownerIdentity":"123456789","virtualBucket":""},"object":{"deltaSize":122539,"eTag":"688A7BF4F233DC9C88A80BF985AB7329","key":"image/a.jpg","size":122539},"ossSchemaVersion":"1.0","ruleId":"9adac8e253828f4f7c0466d941fa3db81161****"},"region":"cn-shanghai","requestParameters":{"sourceIPAddress":"140.205.***.***"},"responseElements":{"requestId":"58F9FF2D3DF792092E12044C"},"userIdentity":{"principalId":"123456789"}}]}handler(json.dumps(event),None)if__name__=="__main__":print(test())like这个,通过构造一个事件对象,可以触发一个模拟事件来触发Serverless应用优化,资源评估还是很重要的,虽然serverless架构是按需付费,但并不代表一定低于传统服务器租用成本,如果你对自己的项目评价不准确,一些指标设置不合理,serverless架构的成本可能是巨大的,一般FaaS平台的收费与三个指标直接相关,即配置的功能规格(如内存规格等),程序消耗的时间和产生的流量费用。通常,程序消耗的时间可能与内存规格和程序本身处理的业务逻辑有关。流量成本与程序本身与客户端交互的数据包大小有关。所以在这三个常用指标中,内存规格可能会因为配置不规范导致计费偏差比较大。以阿里云函数计算为例,假设有一个HelloWorld程序,每天执行10000次。内存产生的费用(不包括网络费用)如表所示。从表中可以看出,当程序可以在128MB内存中正常执行时,如果错误地将内存规格设置为3072MB,每月费用可能会增加25倍!因此,在上线Serverless应用之前,需要对资源进行评估,通过更合理的配置进一步降低成本。合理的代码包规格每个云厂商的FaaS平台对代码包大小都有限制。先不管云厂商对码包的限制,简单来说,码包规范可能带来的影响,可以通过函数的冷启动过程看出来,如图。函数冷启动流程示意图在函数冷启动过程中,当上传的代码包过大,或者文件过多导致解压速度过慢时,加载代码的过程会比较长,这会进一步导致更长的冷启动时间。想象一下,当有两个压缩包时,一个是只有100KB的代码压缩包,一个是200MB的代码压缩包。)下载,即使最高速度可以达到125MB/s,前者的下载时间也不足0.01秒,后者的下载时间为1.6秒。除了下载时间,加上文件的解压时间,两者的冷启动时间可能相差2秒。一般来说,对于传统的web界面,如果要求2秒以上的响应时间,对于很多业务来说其实是无法接受的,所以在打包代码的时候,需要尽可能的减小压缩包体积。以Node.js项目为例,在打包代码包的时候,我们可以使用Webpack等方式压缩依赖包的大小,进一步减小整体代码包的大小,提高冷启动效率功能。实例的合理复用为了更好的解决冷启动问题,更合理的利用资源,各个云厂商的FaaS平台都存在实例复用。所谓实例重用,就是当一个实例完成一个请求后,它不会被释放,而是进入静默状态。在一定时间内,如果分配了新的请求,会直接调用相应的方法,不需要重新初始化各种资源,大大减少了函数冷启动的发生。为了验证,我们可以创建两个函数:函数1:#-*-coding:utf-8-*-defhandler(event,context):print("Test")return'helloworld'函数2:#-*-coding:utf-8-*-print("Test")defhandler(event,context):return'helloworld'点击控制台的“测试”按钮,测试以上两个函数,判断是否在日志中表中输出“测试”,统计结果如表所示。从函数复用记录可以看出,其实是有实例复用的。进一步思考,如果print("Test")语句是初始数据库连接,或者函数1和函数2加载一个深度学习模型,是不是每次请求都会执行函数1,而函数2可以重用现有对象?因此,在实际项目中,可以根据函数2来实现一些初始化操作。例如在机器学习场景中,在初始化时加载模型,避免每次触发函数时都加载模型。在初始化时创建一个链接对象,以避免为每个请求创建一个链接对象。其他一些需要在第一次加载时下载加载的文件在初始化时实现,以提高实例复用的效率。善于利用函数特性各个云厂商的FaaS平台都有一些特性。所谓平台特性,是指这些功能可能不是CNCFWG-ServerlessWhitepaperv1.0中规定或描述的能力,而只是云平台基于自身业务发展,站在用户的角度挖掘和实现的功能和需求,可能只是某个云平台或某些云平台的功能。通常,如果这些功能使用得当,业务绩效将会得到质的提升。1.Pre-freeze&Pre-stop以阿里云函数计算为例,在平台开发过程中,用户痛点(尤其是阻碍传统应用向Serverless架构的平滑迁移)主要有以下几点。异步后台metrics数据延迟或丢失:如果在一次请求中没有发送成功,可能会延迟到下一次请求,或者该数据点可能被丢弃。同步发送指标会增加延迟:如果在每次请求结束后调用Flush这样的接口,不仅会增加每次请求的延迟,还会对后端服务造成不必要的压力。Gracefulfunctionoffline:当实例关闭时,应用需要清理连接,关闭进程,上报状态。函数计算中实例下线,开发者无法掌握,也缺少Webhooks通知函数实例下线事件。基于这些痛点,阿里云发布了RuntimeExtensions功能。此功能扩展了现有的HTTP服务编程模型,将PreFreeze和PreStopWebhook添加到现有的HTTP服务器模型中。扩展开发人员负责实现HTTP处理程序并监控功能实例的生命周期事件,如图所示。扩展编程模型和现有编程模型PreFreeze处理的工作内容简化图:在每个函数计算服务决定冻结当前函数实例之前,函数计算服务会调用HTTPGET/prefreeze路径,扩展开发者负责实现相应的逻辑,以确保完成冻结实例前的必要操作,如等待指标发送成功,如图所示。函数调用InvokeFunction的时间不包括PreFreezeHook的执行时间。PreFreeze时序图PreStop:在每次函数计算决定停止当前函数实例之前,函数计算服务会调用HTTPGET/prestop路径,由扩展开发者负责实现相应的逻辑,确保在函数计算停止之前进行必要的操作实例发布完成,比如等待数据库连接关闭,以及上报,更新状态等,如图。PreStop时序图2.单实例多并发众所周知,各个云厂商的函数计算通常在请求层面是隔离的,即客户端同时发起三个函数计算请求时,理论上三个实例将生成来处理它。这时候,就有可能会涉及到请求之间的冷启动、状态关联等问题。因此,一些云厂商提供了单实例多并发的能力(例如阿里云函数计算)。该能力允许用户为一个函数设置实例并发(InstanceConcurrency),即单个函数实例可以同时处理多个请求,如图所示。单实例多并发效果简图如上图所示。假设同时有3个请求要处理。当实例并发设置为1时,函数计算需要创建3个实例来处理这3个请求,每个实例处理1个请求;当实例并发设置为10时(即一个实例可以同时处理10个请求),函数计算只需要创建一个实例来处理这三个请求。单实例多并发的优点如下。减少执行时间并节省成本。例如,部分I/O功能可以在一个实例内并发处理请求,减少实例数,从而减少整体执行时间。状态可以在请求之间共享。多个请求可以在一个实例中共享数据库连接池,从而减少数据库的连接数。降低冷启动概率。由于可以在单个实例中处理多个请求,因此减少了创建新实例的数量并降低了冷启动的可能性。减少VPCIP使用。在相同负载下,单个实例的多个并发实例可以减少实例总数,从而减少对VPCIP的占用。单实例和多并发的应用场景比较广泛。比如函数中有大量时间等待下游服务响应的场景更适合使用该函数。单实例多并发也不适合应用场景。例如,当函数具有共享状态且不能并发访问时,执行单个请求会消耗大量的CPU和内存资源。这个时候不适合使用单实例多并发。作者简介:刘宇(江宇)国防科技大学电子信息专业博士生,阿里云Serverless产品经理,阿里云Serverless云布道者,CIO学院特聘讲师。原文链接本文为阿里云原创内容,未经许可不得转载。