#serverless
楊凱 中國工信出版集團
大綱#
- 綜述顛覆性影響、理解 sls 和目前技術的定位關係
- FaaS 是 Serverless 核心思想的實際應用技術
- BaaS 是 sls 的另一大分值體系
概述#
#cloudnative 雲原生被提到最多的概念就是 serverless 了
sls 的概念、sls 的開發理念、極低的運維成本、大幅下降的伺服器費用
舉例 github pages,開發者把文件部署為靜態站點,分配域名、訪問服務。屏蔽了很多細節。
舉例 CDN,無需關注細節、節點,全球用戶高速訪問。
可以認為把計算資源作為服務的方式提供產品,複合 serverless 理念,屏蔽技術細節,對外提供服務。
CNCF 在 2018 年發布了 serverless 白皮書
sls 是指無論在應用的構建還是運行,都不用對伺服器進行維護和管理
sls 計算平台應該包含一種或者兩種能力 faas baas
接下來介紹,使用場景,優勢劣勢
faas 的優勢:研發效率高、部署成本低、運維成本低、學習成本低、伺服器費用低、部署方案靈活、系統安全性高
劣勢:平台學習成本高、調試成本高(運行時在雲端,本地調試、日誌查詢困難)、冷啟動、供應商鎖定
使用場景:
- 函數本身無狀態,和持久化伺服器融合
- 函數獨立工作,彼此大量函數聯動計算費用會上升
- 自動伸縮
- 事件驅動,http、資料庫修改、定時事件等
- 冷啟動要求低的場景
faas 本身不支持 http 協議,所以需要通過 api gateway 對外提供 web api
sls 和服務端技術#
單體應用 - 分層架構,UI 層、業務邏輯層 Business Logic Layer、數據訪問層 Data Access Layer
三層架構的基礎上,比如 企業應用架構模式、領域驅動設計兩本書,進一步區分
- 應用層
- 領域層
- 持久層
- 基礎設施層
還是分層的思路,對代碼切分,達到關注點分離 Separation of concerns SOC 的目標。
我能不能抽離 登錄、權限判斷等邏輯,從而在不同業務之間進行復用
微服務 microservices 架構風格,從分佈式架構演變而來。多個獨立小型服務進行輕量 、可控的軟體研發管理。服務之間通過 RPC 實現相互通信,這樣各個服務就可以使用不同的技術棧完成功能。
設計系統的架構受制於組織的溝通結構。康威定律。什麼樣的組織架構,就設計出什麼樣的架構。比如小公司,單體應用,規模擴大,新增人員需要重新熟悉整體內容,這是網狀結構,彼此都需要同步信息,溝通成本指數級增加。
單體拆分為微服務,只關注自己的業務,屏蔽不必要的信息,降低溝通成本
容器化、雲計算、noops- devops 的下一階段,減少研發人在運維的投入,是一種理念。
sls 和前端技術#
bff,後端服務於前端。在前端和後端之間做膠水層,做信息的聚合和裁剪。一個接口完成多個接口的操作。移出不需要的字段等。
這讓接口更加靈活。溝通成本低。減少請求做性能優化、減少數據暴露做安全性
graphQL 在多語言的微服務架構下不容易應用,改造成本太高,目前沒有太多跨語言。跨資料庫統一實現聚合查詢的能力。如果與 serverless 結合才有可能
FaaS 技術#
事件驅動。是一種設計模型。
faas 函數同樣是事件驅動,不同的 trigger 觸發器作為事件源。比如 http 觸發器
函數無狀態足夠簡單。
創建函數。裡面有很多技術細節,現在改版多次了已經。
- 運行時選擇
- 默認的
- 自定義運行時,這種兼容性最高
- 自定義容器,比如 GPU 容器
- 基本信息,名稱、區域、觸發器事件和 http
- 代碼上傳
- 示例 demo
- zip 包壓縮
- oss 上傳
- 文件夾上傳
- 規格設計
- cpu 0.05~16g
- 內存 128M ~ 32 G
- 臨時硬碟 512M、10G
- 如果選擇容器部署,還可以選擇 GPU T4/A10 規格
- 實例並發度。同時處理多少個請求
- 超時時間 60s
- 時區
- 鑑權認證
- 簽名
- jwt
2015 年,開源社區出現了 serverless framework,目標是成為 sls 的框架和生態系統,解決供應商鎖定的問題。
編寫細節忽略
7 函數生命週期#
module.exports.handler = function (request, response, context) {
// code
(async () => {
response.setStatusCode(200);
response.setHeader('content-type', contentType);
response.send(fs.readFileSync(path))
})().catch(err => {
response.setStatusCode(500);
response.setHeader('content-type', 'text/plain');
response.send(err.message);
});
}
8 理解函數運行時#
設計模式 23 種設計模式
消息隊列,能解決高並發的問題,也能實現系統解耦。削峰填谷。保證信息按順序接受。
突然想到 信息觸發的方案,站內信、短信、微信推送等。
9 自建簡易 FaaS#
要保證各函數的安全性,避免互相打擾,隔離的關鍵技術是沙箱 Sandbox
- 使用 docker 隔離
- 使用進程隔離,不如 docker
使用 master 監聽函數調用,啟用子進程 child 執行函數。返回的結果通信給主進程。
這裡使用 child_process.fork()
啟動子進程實現隔離。
如果執行代碼可以用 eval/Function 來比較,最佳的方案還是 node 的 new vm.Script(code)
方案
但 vm 也會有風險,舉例 this.constructor.construcotr
原型鏈的設計,所以沒有原型鏈就好了
const sandbox = Object.create(null)
vm.createContext(sandbox)
vm.runInContext(code,sanbox)
但是也不完美,社區中使用 vm2
,通過 proxy 特性進行封裝,更加安全。
因此,運行時使用 vm2 和 child_process.fork 組合使用,可以實現隔離和用戶代碼執行。
實現 http 協議支持,可以使用 koa 來實現。動態下載函數並執行。。
簡易版完成,但還需要考慮吞吐性能、安全穩定、開發效率。
每次執行都會創建 子進程來執行,這個進程的創建和銷毀管理是性能開銷,高並發時候過多的進程也可能導致崩潰,這就考慮 進程池了。
可以使用 cluster,對 child_process
的進一步抽象封裝,用起來更好用。
使用 cluster 和 vm2 配合 koa 就能實現一個方案了。
問了 gpt,
可以考慮 generic-pool
:這個模塊提供了一個通用的資源池,可以用於管理各種資源,包括進程。你可以使用它來創建一個進程池,從而避免頻繁地啟動和停止子進程。它提供了靈活的配置選項,允許你自定義池的大小、資源分配策略等。
用戶代碼如果用了死循環,就無法結束任務了。設定超時時間。 vm/vm2 都有 timeout 比如設定 5000ms
異步調用問題,默認的超時不起作用,可以考慮自行實現計時器
確保穩定性,資源限制。cpu、內存、磁碟的高強度使用。要限制資源,在 Linux 裡有 CGroup 限制資源,docker 裡也用到了這個能力。
介紹了一堆 CGroup 的概念,略過細節,通過命令就可以限制某個進程最多使用 20% 的 cpu 資源了。有點複雜,gpt 答的挺好
提高效率,內置前端常用服務。
- 簡單的 kv 存儲,使用 vm2 實現 get/set
當然,最好還是 redis
BaaS 技術#
backend as a service。
![[Pasted image 20230923233047.png]]
後續提到了 firebase 一展示提供了很多開箱機用的基礎服務,比如雲資料庫、雲函數、auth、托管、存儲等。
還有崩潰報告、性能監控、test lab、應用分發等功能。
還有拓展類的運營功能
- 應用內消息 in-app messaging
- 分析
- a/b testing
- cloud messaging 雲消息,推送 IM 等
- remote config 配置中心
國內的 leancloud/bmob 等,整體完整性還有差距。
資料庫設計原則部分。
比如 posts 和 comments 兩張表查詢,會有 select 1+n 的問題,也就是需要先查詢 n 條記錄找到信息,再查詢 n 次對應的數據。sql 中使用 join 就行
舉個例子,最近五條評論的內容,所屬文章標題。
使用 sql 比較簡單。如果提前設計成嵌入的方案就容易。如果已經變成引用的方案了,可能需要保留更多冗餘內容。設定一個新集合,最新评论的集合,冗餘字段。如果有讀寫問題,就可以改成快取,一小時更新一次。這帶來的問題是,刪除時需要同步刪除多份。
如果使用內嵌,一次查詢就可以了,而且查詢性能好。對於嵌套的複雜數據就不好了。先把數據聚合再排序,實現也是放入內存中,大量數據可能就不好。
快速介紹了 CDN、對象存儲等功能
用戶鑑權介紹了 OneID 不流行的趨勢,介紹了 OAuth 2.0
最終納入了 IETF 組織,實現了標準化。
oauth2 裡提供了四中授權模式
- 授權碼 auth code,默認
- 簡化模式
- 密碼
- 客戶端憑證
後面三種比較特殊,不用管
OAuth 解決的是授權,不是用戶認證,引入了 OIDC - openID Connect
進一步拆分了 id token 和 access token
jwt 是 rfc 7519
對接第三方會比較費勁,就產生了 IDaaS 比如 auth0 網站和 authing 網站
- 身份認證 賬戶授權
- sso single sign in 一個應用登錄,多個應用共享
- 對外提供 oauth2
- 統一發送郵件、短信重置密碼
- 企業身份登錄
- 兩步驗證
可以看看,有一些 user/rule/rules/hooks 等
沒了。
總結展望#
第二部分比較精彩,其他一般。