什么是 SAM?
sam 全称是:Serverless Application Model,也就是无服务器应用模型。
它使用 yaml 语法来描述一个应用程序,服务商会对.yml
后缀的 sam 文件进行解析,并按照文件描述部署相关服务。
应用场景
SAM 的概念最初由 AWS 提出,用来描述程序所需要的 Lambda function、Cloud
DB 等云端资源。
腾讯云云开发的扩展能力中,也使用 SAM 来描述扩展能力所需要的云开发资源,包括云函数、存储、数据库,甚至其他的云能力,例如短信发送。短信验证码登录 本身就是扩展,用到了腾讯云的短信能力。
再发挥一下,sam 可以用来描述简单的 UI 视图,尤其适合表单的应用场景,如下所示:
实现简易的 SAM
定义 SAM
因为 sam 是 yaml 语法文件,所以需要解析 yaml 语法,使用yaml.js
举个例子,某个程序需要使用到云函数,并且需要创建两个数据表,SAM 文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| ApplicationName: 测试程序
Function: Container: nodejs 8.9 Timeout: 60 Corn:
Database: Collections: - CollectionName: 'ext-collection-a' - CollectionName: 'ext-collection-b'
|
数据校验
由于前端输入的数据不可信,后端需要对传入的 SAM 进行校验。
随着依赖的资源字段增加,单纯使用 if-else
的逻辑判断,会让代码变得难以维护,可读性非常差。
通常有 2 种数据校验的思路:
- 借助
joi.js
,在代码中增加校验逻辑
- 使用
ajv.js
,分离 Schema 和代码逻辑
第 2 种思路耦合度更低,并且规则的改动和维护,不涉及代码改动,产品和运营同学也可以来维护规则。
按照 schema 的 ajv 语法,以前面的 SAM 文件为例,schema 的内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| { "type": "object", "properties": { "ApplicationName": { "type": "string" }, "Function": { "type": "object", "required": ["Container", "Timeout"], "properties": { "Container": { "type": "string" }, "Timeout": { "type": "number" }, "Corn": { "type": ["string", "null"] } } }, "Database": { "type": "object", "Collections": { "type": "array", "items": { "properties": { "CollectionName": { "type": "string" } } } } } } }
|
封装 ajv 的验证逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const Ajv = require('ajv')
function validateSchema(obj, schemaFilePath) { const schemaJson = require(schemaFilePath)
const ajv = new Ajv() const validate = ajv.compile(schemaJson) const valid = validate(obj) if (!valid) { console.log('>>> 错误字段信息:', validate.errors) } return valid }
|
变量注入
有些时候,某些变量是动态的。例如,用户信息可能在运行过程中被注入到上下文,数据集合名称需要前端用户表单传入。
举个例子,前面创建的两个数据集合的名称由前端表单传入,对应字段是:collectionNameA
和collectionNameB
。
1 2 3 4 5 6 7 8 9
| Database: Collections: - CollectionName: '${env.collectionNameA}' - CollectionName: '${env.collectionNameB}'
|
整个流程总结:
- 服务端解析预设的 SAM 配置
- 识别
${}
特殊字符串,替换变量
- 验证是否符合 Schema 定义的规则
参考链接