玩转AIGC训练营:课时2:函数计算是如何工作的?
课时2:函数计算是如何工作的
内容介绍:
一、函数计算完整的请求和调链路
二、函数调用
三、函数执行
四、冷启动
本节课主页讲如何触发函数执行以及函数计算如何处理这些请求。
主要分为三个部分:
①概述中介绍函数计算调用的整个列录;
②函数调用中介绍函数计算的调用方式,包括同步调用、异步调用以及他们之间的区别;
③函数执行中介绍函数计算的执行过程,着重说明了什么是冷启动以及避免冷启动的方法
一、函数计算完整的请求和调链路。
如图所示
1、函数计算是事件驱动的无服务器应用,事件驱动是说可以通过事件源自动触发函数执行。比如说当有对象上传至 OSS 中的时候会自动触发函数对新上传的图片进行处理;
函数计算支持丰富的事件源类型,包括日志服务、对象存储、表格存储、消息服务、API 网关、CDN 等等。
除了通过事件源触发函数执行也可以 API 和 SDK 直接来调用函数,同样也支持非常丰富的 SDK,像 Node.js、Python、Java、PHP、Golang 等等;
2、调用函数分为同步调用和异步调用,当请求到达函数计算的时候,函数计算会为请求分配执行环境,如果是异步调用,函数计算会将请求事件先存入队列中等待消费。
二、函数调用
①同步调用
特性:
*服务端会立即返回计算结果
*执行过程中遇到错误,会将错误返回客户端,函数计算不会对错误进行重试,需要客户端添加重试机制
同步调用是说客户端期待服务器立即返回计算结果,请求到达函数计算的时候会立即分配执行环境、执行函数,这种就非常适合一些外部类型应用,比如 HEP 触发器 API 网关触发器,以 API 网关为例 API 网关同步触发函数计算,客户端会一直等待服务端的执行结果,如果执行过程中遇到了错误;比如说函数错误,函数计算会直接将错误返回客户端,而不会对错误进行重试,这种情况下需要客户端自主添加重试机制做错误处理。
②异步调用
特性:
*异步调用将触发请求放到队列中就返回,不会等待函数调用结束
*执行过程中遇到错误,会对错误进行重试,函数错误重试三次,系统错误会以指数退避方式无限重试
*适用于批量数据处理
异步调用的特性是客户端不急于知道结果,函数计算会将请求丢入到队列中向客户端反馈成功而不会等到函数执行结束,异步其实也起到了一个雪峰填补的作用,可以避免瞬间的请求对后端带来的冲击;
在队列中函数计算的执行机器会逐渐消费队列中的请求,然后分配执行环境、执行函数;
如果执行过程中遇到错误的话,函数计算会对错误进行重试。会有两种情况,①函数错误、②系统错误;函数错误会重试三次,系统错误会以指数退避的方式无限重试直至成功。
异步调用适合于数据的处理,比如 OSS 触发器可以触发函数来处理音频、视频,日志触发器可以触发函数来清洗日志,这些场景全都是对延时不敏感又需要尽可能保证任务执行成功的场景。如果用户需要了解失败的请求并对请求做自定义处理可以使用功能。
函数计算是 Serverless 的,但是不是说无服务器,只是说开发者无需关心服务器,函数计算会为开发者分配执行环境。
三、函数执行
如图所示为函数执行的整体流程图。
当函数第一次被调用的时候函数计算需要动态的调度实例,下载代码、解压代码、启动实例得到一个可执行函数的代码环境,然后在系统分配的实例中真正的执行用户的初始化函数,执行函数的业务逻辑,调度实例启动实例的过程就是系统的冷启动。
函数逻辑执行结束后不会立即释放掉实例。图中 request 1执行完以后会有一段的时间没有立即释放;当有新的调用的时候就会复用这个实例,比如说上图中的 Request 2由于执行环境已经分配好了, Request 2就可以直接复用不会遇到冷启动(不会再重新去调度、分配实例来下载代码、解压代码),Request 2结束之后也会等待一段时间,如果这段时间没有新的请求分配到实例上,系统就会回收实例,释放执行环境,实例释放后新的请求如果再来,再看 Request 3那就还需要函数计算来重新调度实例、下载代码、解压代码、启动实例又回到冷启动。所以为了尽可能减小冷启动带来的影响,要想办法避免它,降低冷启动带来的延时。
四、冷启动
降低冷启动延时:
*降低代码包大小
*使用 Initializer 函数
*保持请求连续稳定
如图所示有两种方式来避免冷启动。
①是使用预留实例,预留实例是使用用户预留的实例会立即分配实例并释放,在预留的过程中就准备执行环境,请求结束后系统不会自动回收实例;所以它的特点是不由系统自动的分配回收是由用户控制实例的周期可以常驻不销毁,这将彻底消除实例冷启动带来的延时毛刺提供极致性,也为在线应用清理至函数计算扫清障碍。
②是业务场景不适合使用预留实例,就要利用一些方法,比如说降低代码包的大小(减少下载代码包的延时、解压代码包的时间); Initializer 函数是实例的初始化函数,在同一个实例中执行且只执行一次,所以可以将一些耗时的公共逻辑放到 Initializer 中,比如说在 nas 中加载 inlet,建立链接;尽量保持请求连续稳定,避免突发的流量,比如系统已经启动实例不足以支撑大量突发流量就会启动新的实例,这将带来不可避免的冷启动。