函数计算是一个和 Serverless 相关的概念,函数计算可以理解为 FaaS,目前 Serverless 并没有一个很官方的定义,业内普遍认为 Serverless = BaaS + FaaS。
¶一、Serverless
Serverless 是一种新型的互联网架构 —— 无服务器架构,这里的无服务器不是指不需要服务器,而是开发者可以不管理服务器等基础设施。其实 Serverless 也谈不上新,因为这个概念在 2012 年就已经提出了,简单看下 Serverless 的发展历史:
云计算的发展过程从 IaaS,PaaS,SaaS 到最新的 Serverless,介绍下这些基本概念就可以看出 Serverless 是云计算发展到某一阶段的必然产物,可以节省运维成本和开发成本。
- IaaS:基础设施即服务,服务商提供物理层基础设施资源,开发者需要购买并选择操作系统,安装软件、部署程序、监控应用。
- PaaS:平台即服务,服务商提供操作系统、数据库、负载均衡器和其他中间件,相比 IaaS,开发者仅需要控制上层的程序部署与应用托管的环境即可。
- SaaS:软件即服务, 服务商提供基于软件的解决方案,如 OA、CRM、ERP、Office、iCloud 等,客户只需要通过服务商平台获取软件使用即可。
- BaaS:后端即服务,如提供文件存储、推送服务、身份验证服务等。
- FaaS:函数即服务,服务商提供一个平台,允许开发者开发、允许和管理应用程序,而无需构建和维护基础架构,通常在构建微服务应用时使用。
¶二、函数计算
函数计算是阿里云作为云服务商提供的一项服务能力,类似的服务还有亚马逊的 Lambda、腾讯云的云函数、Google Cloud Functions 等。本篇随笔就介绍一下阿里云的函数计算,并进行小场景实践:基于 egg 和 MySQL 提供 Web 服务。
阿里云对函数计算(Function Compute)的定义是:一个事件驱动的全托管 Serverless 计算服务,无需管理服务器等基础设施,只需编写代码并上传,函数计算会准备好计算资源,并以弹性、可靠的方式运行代码,并提供日志查询、性能监控和报警等功能。
我们可以对比一个应用从开发到上线的过程:
¶2.1、工作流程
- 1、开发者编写程序,函数计算支持的 开发语言列表。
- 2、开发者上传程序到函数计算。
- 3、触发函数执行,触发方式包括OSS、API网关、日志服务、表格存储以及函数计算API、SDK等。
- 4、动态扩容,根据用户请求量自动扩容,减轻运维压力,开发者和用户无感知。
- 5、按函数执行时间计费。
¶2.2、特点
-
高效免运维
-
弹性执行
-
按量付费,低成本
-
事件驱动
-
调试麻烦
-
构建复杂
-
休眠启动
¶2.3、典型场景
- Web 应用
- 对计算能力有很强的弹性诉求
- 事件驱动型的应用
¶三、实践
可参考官方文档:快速入门。创建函数的方法有很多种,我采用的是通过命令行创建函数。
¶3.1、开通函数计算服务
登录阿里云控制台,搜索函数计算并开通。
¶3.2、安装命令行工具
全局安装命令行工具 Funcraft:
1 | npm install @alicloud/fun -g |
使用 fun 工具部署可以去全局定义账户信息,输入fun config
依次配置 Account ID(阿里云账号 ID)、AccessKey ID、AccessKey Secret、Default Region Name。如果账号是 RAM 用户,Account ID 需要配置为阿里云账号的 ID,AccessKey ID、AccessKey Secret 为 RAM 用户的密钥。推荐全局配置,完成配置后,Funcraft 会将配置保存到用户目录下的.fcli/config.yaml
文件中。
¶3.3、编写代码
先写个 hello-world:
1 | mkdir hello-world |
写个 GET 和 POST 的接口,egg 会有 CSRF 攻击的限制,可以在/config/config.default.js中添加 csrf 配置的代码:
1 | module.exports = appInfo => { |
¶3.4、部署过程
部署时会同时上传 node_modules,所以使用 deploy 命令中使用了npm i --production
。也可以通过 层 的概念去上传依赖包,层可以理解为依赖库、自定义运行环境,此时可配置.funignore
文件,过滤不上传的文件或目录。
1 | rm -rf node_modules |
确认服务和函数的名称后,fun 工具会生成对应的配置文件:
(1)新增配置文件
1 | ROSTemplateFormatVersion: '2015-09-01' |
(2)自定义运行环境,需要将可执行文件 bootstrap 的顶部配置更新为:
1 | #!/bin/bash |
同时,给予 bootstrap 文件可执行权限(777 或 755):
1 | chmod 777 bootstrap |
部署代码到后,函数计算会运行bootstrap 文件,该文件指定运行端口、启动程序。
1 | // bootstrap |
¶3.5、部署完成
继续命令行的部署,配置自定义域名后进行验证。
¶四、复杂场景
本节代码:https://github.com/liuxy0551/dingtalk-robot
¶4.1、实现效果
可以发送消息到指定钉钉群,效果如下:
¶4.2、通过钉钉群机器人发消息
1 | /** |
/app/service/robot.js
:
1 | // 获取机器人列表 |
¶4.3、百度统计
通过定时任务拉取百度统计的埋点数据,并通过统一的钉钉群机器人发送到群
1 | // 百度统计实现 |
1 | // 定时触发器 |
¶4.4、记账啦
通过定时任务拉取微信小程序的数据,并通过统一的钉钉群机器人发送到群
¶4.5、从 MySQL 查询数据
¶五、使用心得
¶5.1、版本管理
操作路径:控制台 -> 函数计算 -> 服务及函数 -> (选择一个服务)版本管理。
每次部署时可以新建一个版本,第一次新建版本后可以在此版本的基础上新建别名,如:prod,并将自定义域名(第 3 条)、函数的 http 触发器中 版本/别名 选择为 prod。后续部署时,可以新建版本,需要该版本生效时,可以简单编辑 prod 别名对应的版本即可,同时别名支持版本配比,可进行灰度测试。
¶5.2、配置导出
操作路径:控制台 -> 函数计算 -> 服务及函数 -> (选择一个服务)函数列表 -> 函数名称(点击函数名称) -> 概览 -> 导出 -> 导出配置将导出的 template.yml 文件放到项目中,这样控制台配置的配置项就不会被 deploy 覆盖掉。
注意
控制台导出的配置文件可能有部分缺失,需要和本地已有的 template.yml 文件对比,保留部分字段,如:CodeUri
¶5.3、自定义域名
操作路径:控制台 -> 函数计算 -> 自定义域名每个路由的 版本/别名 在开发调试时先选择 LATEST,等待上线时,按照第 1 条的版本管理,选择别名。
¶5.4、日志查询
操作路径:控制台 -> 函数计算 -> 服务及函数 -> (选择一个服务)函数列表 -> 函数名称(点击函数名称) -> 日志查询日志内容包含的内容如:接口 url、报错信息。
注意
当函数的 单实例并发度 大于 1 时,只有高级查询,等于 1 时,有简单查询和高级查询。
¶5.5、请求环境区分
使用函数时如果需要区分生产环境和测试环境,可以发布不同的版本,并创建多个触发器,设置触发器指向不同的版本/别名,如下图:
自定义域名中创建两个域名,用来区分环境,路径可按下方示例填写,生产和测试选择不同的版本/别名即可。