設計實現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定義的規則

參考連接

相關文章
相關標籤/搜索