一 概念
阿里云的函数计算——FC ,是一个事件驱动的全托管 Serverless 计算服务,开发者无需管理服务器等基础设施,只需编写代码并上传。函数计算FC 会为您准备好计算资源,并以弹性、可靠的方式运行您的代码。
阿里云函数计算详细文档请参见: https://help.aliyun.com/document_detail/73329.html?spm=a2c4g.11186623.6.559.5b8a2b81Zkr7gO
二 函数计算创建及使用流程
如上图所示,函数计算的创建和使用过程,主要包括下面四个步骤:
1、创建服务,
2、创建函数,
3、创建触发器(可选)
4、执行函数
业务增益和查看日志可选,非必要流程。【在控制台创建好的函数,如果要查询日志需要单独开通日志服务(SLS),同时会收取费用。所以可以使用时约定好各种错误的标识符用于区分错误类型,在调用前自己打印log等方式来解决这个问题】
三 函数类型及调用方式
3.1 支持开发语言列表
目前支持的语言列表包括:Node.js、Java, Python, Php, C#, Go, Ruby, PowerShell, TypeScript, F#
3.2 关于服务
函数计算中,服务相当于函数的分组,并且仅支持一级。
3.3 函数类型
新建函数,支持事件函数 和 HTTP函数两种类型。二者入参不同,函数被触发/调用的方式也不同。 其中,
1、HTTP函数:(只)支持以HTTP/HTTPS请求方式调用,可自行配置调用方式,GET/POST/PUT/DELETE;入口函数参数:req, resp, context
2、事件函数:支持多种触发器,对象、日志、定时、CDN事件等等。入口函数参数: event,context,callback
3.4 调用方式
事件函数的支持触发类型如下:
四 我们的使用方式
为了简化调用方式,并且当前服务没有特别的性能要求,所以采用了HTTP函数,POST/GET请求方式创建函数及触发器。
自带的函数计算示例:
“路径”列,是函数计算的请求地址,我们使用postman或firefox的httpclient插件发送post请求就可以获取返回值。
如上图所示,返回的是文本类型内容,设置响应类型后可以正常得到结果。
有一点需要我们注意:Http Trigger 会自动在响应头中强制添加 'Content-Disposition: attachment' 字段,此字段会使得返回结果在浏览器中以附件的方式下载。此字段无法覆盖,使用 自定义域名 可以避免该问题。
当我们需要返回json或文本格式时,就必须设置自定义域名,所以,还需要在域名解析控制台添加或使用现有域名,并配置解析规则。
新增一项CNAME解析规则即可,参考配置说明:
五 应用中遇到的一个问题
最近在项目中要使用阿里云的函数计算功能,所以开始按照说明尝试本地部署示例服务,并编写所需功能。参考文档:https://fc.console.aliyun.com/fc/guide/cn-hangzhou#tool
环境为macos。
按照说明,npm install @serverless-devs/s -g 安装完成,并且示例程序:image-style-transfer也安装完毕。
但s deploy执行时报错:
End the pre-hook Error: "accountid" must be passed in Project StyleComponent failed to execute End of method: deploy ********** The operation was not fully successful ********** > Project Run Error: StyleComponent Error: Error: "accountid" must be passed in
可以看到提示,是部署过程中缺失accountid导致。 如果是首次执行 s deploy命令,在执行过程中能看到提示在控制台输入accountid 和 秘钥信息。但我当时没有注意,敲了多次Enter,导致错过了输入的时机。而官方文档也并没有在示例中给出相应的问题和解决方法。
仔细研读完整的函数计算相关文档之后,按照一般的函数计算部署方式,我们需要提供一个.env文件,其中存储accountid 和 ACCESS_KEY_SECRET等信息。
六 一些最佳实践
关于冷启动:
所谓冷启动,是指函数计算被首次调用时,需要做一些初始化动作,导致响应耗时较长。回到根本,函数计算是一种弹性扩容的能力支持,让我们以调用远程方法的方式来执行一些计算逻辑,而不用关心高并发带来的资源消耗、动态扩容支持、费用等问题。它的实现采用的是k8s+docker方式,初始资源加载包括创建pod、拉取镜像等动作,那么显然会大于仅仅执行计算逻辑的耗时。
为了解决这个问题,我们采用的是定时执行,类似于保活的策略,来保证容器不会被销毁。
阿里云最佳实践文档:https://help.aliyun.com/document_detail/140338.html?spm=a2c4g.11174283.6.673.20685212lavP6J
文档中,完整的解决思路包括:
- 精简紧凑的代码包: 开发者要尽可能瘦身代码包,去掉不必要的依赖。降低 Download/Extract Code 的时间。例如对 Nodejs 函数使用 npm prune, 对 Python 函数使用autoflake,autoremove 去除没有使用的依赖。另外一些第三方库中可能会包含测试用例源代码,无用 binary 和数据文件。有选择地删除无用文件可以降低函数代码下载解压时间。
- 选择合适的函数语言: 由于语言理念的差异,Java 运行时冷启动时间通常要高于其他语言。对于冷启动延迟敏感的应用。在热启动延迟差别不大的情况下,使用 Python 这样的轻量语言可以大幅降低长尾延迟。
- 选择合适的内存: 在并发量一定的情况下,函数内存越大,冷启动表现越优。
- 降低冷启动概率:使用定时触发器预热函数使用 Initializer 函数入口,函数计算会异步调用初始化接口,消除掉 “User Code Init” 的时间,在函数计算系统升级或者函数更新过程中,用户对冷启动无感知。