开发者学堂课程【Serverless 技术进阶:【音频】Serverless应用开发经验】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/995/detail/15052
【音频】Serverless应用开发经验
内容介绍:
一、如何上传文件
二、文件读写与持久化方法
三、慎用部分Web框架的特性
四、注意应用组成结构
五、善于利用函数的厂商特性
六、传统框架迁移方案与策略
一、如何上传文件
在传统Web框架中,上传文件是非常简单和便捷的,例如 Python的Flask框架,但是在Serverless架构下,却不能直接上传文件,原因有以下几点:
(1)一些云平台的API网关触发器会将二进制文件转换成字符串;不便直接获取和存储;
(2)API网关与FaaS平台之间传递的数据包有大小限制,很多平台被限制在6M;
(3)FaaS平台大都是无状态的,即使存储到当前实例中,也会随着实例释放而导致文件丢失;
因此,传统框架中常用的上传方案是不太适合在Serverless架构中直接使用的,在Serverless架构上传文件的方法通常有两种:
第一种是 BASE64后上传,持久化到对象存储或者是NAS 中,这种做法可能会触及到API 网关与FaaS平台之间传递的数据包有大小限制,所以一般使用这种上传方法的通常是上传头像等小文件的业务场景;
第二种上传方法是通过对象存储等平台来上传,因为客户端直接通过密钥等信息来将文件直传到对象存储是有一定风险的,所以通常情况是客户端发起上传请求,函数计算根据请求内容进行预签名操作,并将预签名地址返回给客户端,客户端再使用指定的方法进行上传,上传完成之后,可以通过对象存储触发器等来对上传结果进行更新。
二、文件读写与持久化方法
应用在执行过程中,可能会涉及到文件的读写操作,或者是一些文件的持久化操作。在传统的云主机模式下,通常情况下是可以直接读写文件,或者将文件持久化某个目录下,但是在Serverless架构下并不是这样的。
由于FaaS平台是无状态的,并且用过之后会被销毁,所以文件如果需要持久化并不能直接持久化在实例中,但是可以选择持久化到其他的服务中,例如对象存储、NAS等。
三、慎用部分Web框架的特性
1、异步
函数计算是请求级别的隔离,所以可以认为这个请求结束了,实例就有可能进入到一个“静默”的状态了,而在函数计算中,API网关触发器通常是同步调用,以阿里云函数计算为例,通常只在定时触发器、0SS事件触发器、MNS主题触发器和IoT触发器等几种情况下是异步触发,这就意味着当API网关将结果返回给客户端的时候,整个函数就会进入“静默”状态,或者被销毁,而不是会继续执行完异步方法,所以通常情况下像Tornado等框架就很难在Serverless架构下发挥其异步的作用。
当然,如果使用者需要异步能力,可以参考云厂商所提供异步方法,还是以阿里云函数计算为例,阿里云函数计算为用户提供了一种异步调用能力,当函数的异步调用被触发后,函数计算会将触发事件放入内部队列中,并返回请求ID,而具体的调用情况及函数执行状态将不会返回。如果用户希望获得异步调用的结果,则可以通过配置异步调用目标来实现。
2、定时任务
Serverless架构下,应用一旦完成当前请求,就会进入到“静默”状态,实例甚至会被销毁,所以这就导致一些自带定时任务的框架没有办法正常执行定时任务。
因为函数计算通常是由事件触发,不会自主定时启动,例如Egg项目中设定了一个定时任务,但是在实际的函数计算中如果没有通过触发器触发该函数,那么该函数是不会被触发,函数也不会从内部自动启动来执行定时任务,所以此时可以使用各个云厂商为其FaaS平台提供的定时触发器,通过定时触发器触发指定方法,来替代定时任务。
四、注意应用组成结构
1、静态资源与业务逻辑
在Serverless 架构下,静态资源更应该在对象存储与CDN的加持下对外提供服务,否则所有的资源都在函数中,并通过函数计算对外暴露,不仅仅会让函数的真实业务逻辑并发度降低,也会造成更多的成本支出。
尤其是将一些已有的程序迁移到Serverless架构上,如Wordpress等,更是要注意将静态资源与业务逻辑进行拆分,否则在高并发的情况下,性能与成本都将会受到比较严格的考验。
2、业务逻辑的进一步拆分
在众多云厂商中,函数的收费标准都是依靠运行时间和配置的内存,以及产生的流量进行收费的。如果一个函数的内存设置不合理,会导致成本成倍增加。因此,要保证内存设置合理,更要保证业务逻辑结构的可靠性。
以阿里云函数计算为例,当一个应用,有两个对外的接口,其中有一个接口的内存消耗在128MB 以下,另一个接口的内存消耗稳定在3000MB左右。这两个接口,平均每天会被触发10000次,并且时间消耗均在100ms。
如果两个接口写到一个函数中,那么这个函数可能需要将内存设置在3072MB,同时在用户请求内存消耗较少的接口时,可能在冷启动的情况下难以得到较好的性能表现;如果两个接口分别写到两个函数中,则两个函数内存分别设置成128MB以及3072MB即可。
五、善于利用函数的厂商特性
各个云厂商的FaaS平台都有一些“平台特性”,所谓的平台特性就是说这些功能可能并不是《CNCF WG-Serverless Whitepaper vl.0》中规定的能力,或者描述的能力,仅仅是作为云平台根据自身业务发展和诉求,从用户角度出发挖掘出来,并且实现的功能,可能只在某个云平台或者某几个云平台所拥有的功能,这类功能一般情况下如果利用得当会让业务性能等有质的提升。
以阿里云函数计算为例,在平台发展过程中,挖掘出用户痛点,尤其是阻碍传统应用平滑过移全Serverless架构:
①异步背景指标数据延迟或丢失:如果在请求期间没有发送成功,则可能被延迟至下一次请求,或者数据点被丢弃。
②同步发送指标增加延迟:如果在每个请求结束后都调用类似 Flush接口,不仅增加了每个请求的延迟,对于后端服务也产生了不必要的压力。
③函数优雅下线:实例关闭时应用有清理连接,关闭进程,上报状态等需求。在函数计算中实例下线时机开发者无法掌握,也缺少Webhook 通知函数实例下线事件。
根据这些痛点发布了运行时扩展功能。该功能在现有的HTTP服务编程模型上扩展,在已有的HTTP服务器的模型中增加了PreFreeze和PreStop webhooks。扩展开发者实现HTTP handler,监听函数实例生命周期事件。
PreFreeze:在每次函数计算服务决定冷冻当前函数实例前,函数计算服务会调用HTTP GET /pre-freeze路径,扩展开发者负责实现相应逻辑以确保完成实例冷冻前的必要操作,例如等待指标发送成功等。函数调用InvokeFunction的时间不包PreFreeze hook的执行时间。
PreStop:在每次函数计算决定停止当前函数实例前,函数计算服务会调用HTTPGET /pre-stop路径,扩展开发者负责实现相应逻辑以确保完成实例释放前的必要操作,如关闭数据库链接,以及上报、更新状态等。
六、传统框架迁移方案与策略
Serverless 范围越来越广,但本质上它是一个全新的思路,一种新的编程范式,在这种新的架构下,或者说新的编程范式下,使用全新的思路来做Serverless应用是再好不过的了。
但是实际上并不是这样的,原生的Serverless开发框架是非常少的,以Web框架为例,目前的主流的Web框架“均不支持Serverless模式部署”,一方面是要尝试接触Serverless,一方面又没办法完全放弃传统框架,所以将传统框架如何更简单、更快速、更科学地部署到Serverless架构上就是一个值得探讨的问题。接下来结合两个案例分享一下迁移思路,首先是传统框架迁移案例。
1、传统迁移案例
请求集成方案实际上就是把真实的API网关请求,直接透传给FaaS平台,而不在中途增加任何转换逻辑。
以阿里云函数计算的HTTP函数为例,当想要把传统框架(例如Django,Flask,Express,Next.js等)迁移部署到阿里云函数计算平台上,并且体验Serverless带来的按量付费,弹性伸缩等红利时,就需要体验阿里云函数计算的HTTP函数和 HTTP触发器。
2、通过开发者工具快速迁移/部署
如果通过开发者工具进行传统框架的支持,可以直接通过Serverless Devs的命令,进行案例的项目的创建。
这部分同样涉及众多代码和图表,同学们可以通过本课文档自行练习。