设计实现SAM--无服务器应用模型

Author:心谭
From:【Serverless】设计实现SAM--无服务器应用模型
Des: 专一算法与 web 开发的技术博客javascript

什么是SAM?

sam全称是:Serverless Application Model,也就是无服务器应用模型。html

它使用yaml语法来描述一个应用程序,服务商会对.yml后缀的sam文件进行解析,并按照文件描述部署相关服务。前端

应用场景

SAM的概念最初由AWS提出,用来描述程序所须要的Lambda function、Cloud DB等云端资源。java

腾讯云云开发的扩展能力中,也使用SAM来描述扩展能力所须要的云开发资源,包括云函数、存储、数据库,甚至其余的云能力,例如短信发送。短信验证码登陆 自己就是扩展,用到了腾讯云的短信能力。node

再发挥一下,sam能够用来描述简单的UI视图,尤为适合表单的应用场景,以下所示:git

实现简易的SAM

定义SAM

由于sam是yaml语法文件,因此须要解析yaml语法,使用yaml.jsgithub

举个例子,某个程序须要使用到云函数,而且须要建立两个数据表,SAM文件以下:web

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 的内容以下:

{
    "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的验证逻辑:

const Ajv = require('ajv')
/**
 * 验证obj是否符合 Schema 定义
 * @param {object} obj
 * @param {string} schemaJson 
 * @return {boolean}
 */
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
}

变量注入

有些时候,某些变量是动态的。例如,用户信息可能在运行过程当中被注入到上下文,数据集合名称须要前端用户表单传入。

举个例子,前面建立的两个数据集合的名称由前端表单传入,对应字段是:collectionNameAcollectionNameB

# 云数据库资源
Database:
    # 须要建立的数据集合
    Collections: 
        -
            CollectionName: '${env.collectionNameA}'
        -
            CollectionName: '${env.collectionNameB}'

整个流程总结:

  • 服务端解析预设的SAM配置
  • 识别${}特殊字符串,替换变量
  • 验证是否符合Schema定义的规则

参考连接

相关文章
相关标签/搜索