Author:心譚
From:【Serverless】設計實現SAM--無伺服器應用模型
Des: 專注演算法與 web 開發的技術部落格
什麼是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檔案如下:
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
}
變數注入
有些時候,某些變數是動態的。例如,使用者資訊可能在執行過程中被注入到上下文,資料集合名稱需要前端使用者表單傳入。
舉個例子,前面建立的兩個資料集合的名稱由前端表單傳入,對應欄位是:collectionNameA
和collectionNameB
。
# 雲資料庫資源
Database:
# 需要建立的資料集合
Collections:
-
CollectionName: '${env.collectionNameA}'
-
CollectionName: '${env.collectionNameB}'
整個流程總結:
- 服務端解析預設的SAM配置
- 識別
${}
特殊字串,替換變數 - 驗證是否符合Schema定義的規則