本文對serverless架構的基礎概念,工作原理,應用場景以及具體產(chǎn)品進行詳細解析。
基礎概念
serverless:無服務器架構,即在無需管理服務器等底層資源的情況下完成應用的開發(fā)和運行,是云原生架構的核心組成部分。
通俗來說,如果將購買一臺物理服務器比作 買車 ,購買云服務器就類似于 租車 (租賃期間需要駕駛和維護,且即使閑置也需付費),那么serverless則類似于 出租車 (只需乘坐,按里程計費)。
從技術層面來說,我們可以簡單理解為: serverless = FaaS + BaaS 。一個完整的serverless應用一般由FaaS層負責無狀態(tài)的計算,由BaaS層負責狀態(tài)的存儲:
- FaaS(函數(shù)即服務,F(xiàn)unction as a Service):將函數(shù)代碼托管給云產(chǎn)商,以服務形式運行,支持事件觸發(fā)。代表產(chǎn)品有騰訊云SCF、AWS Lambda等。
- BaaS(后端即服務,Backend as a Service):指云平臺提供的后端組件整合,開發(fā)者無需開發(fā)和維護后端服務,通過API/SDK的調(diào)用便可獲得例如數(shù)據(jù)存儲(對象存儲、云數(shù)據(jù)庫、云中間件等)、消息推送、賬號管理、地圖定位、AI、IoT等能力。

特點及優(yōu)勢:
- 免運維 :無需管理基礎設施 —> 可以專注業(yè)務開發(fā)
- 按量計費 :閑時不計費 —> 降低成本
- 彈性伸縮 :峰時自動擴容 —> 無需考慮可用性問題
劣勢及適用場景:
- 冷啟動延遲: 一定時間內(nèi)的首次調(diào)用可能需要冷啟動(如進行加載代碼、拉起容器等任務)—> 適合對響應速度要求不是太高的接口,更適合異步任務,不適合啟動耗時久的JAVA項目
- 開發(fā)和管理設施: serverless應用的調(diào)試、測試、排障、發(fā)布等設施暫不成熟 —> 目前更適合后端邏輯不太復雜的輕量級應用
- 云產(chǎn)商綁定: 不同云產(chǎn)商提供的組件(如存儲)接口不同,可能增加未來遷移成本 —> 使用標準化框架,并在設計時盡量隔離通用邏輯層和BaaS依賴層
工作原理
各個平臺對云函數(shù)的實現(xiàn)在原理上基本相似,核心都是動態(tài)的啟動實例去執(zhí)行函數(shù)代碼,且完成后實例會保留一定時間窗口。大致的底層架構如下圖,其中步驟(1) (2) (3) (4) 為冷啟動調(diào)用流程,(5) 為非冷啟動調(diào)用。

1.函數(shù)注冊
用戶在控制臺(或命令行)提交函數(shù)代碼到云平臺,并進行函數(shù)配置。代碼一般會被作為靜態(tài)資源保存(如對象存儲),而函數(shù)的元信息會被存入數(shù)據(jù)庫中(如MySQL)。
2.函數(shù)觸發(fā)
云函數(shù)的觸發(fā)可以分為同步和異步兩種情況:
- 如果是同步請求則等待函數(shù)執(zhí)行結果后返回
- 如果是異步請求則可以投遞到隊列后直接返回
3.函數(shù)執(zhí)行
云函數(shù)的執(zhí)行可以分為窗口內(nèi)首次執(zhí)行(冷啟動)和非首次執(zhí)行兩種情況:
- 如果是首次執(zhí)行,則需要進行宿主機調(diào)度,在宿主機拉起容器實例,下載函數(shù)代碼,然后執(zhí)行代碼。
- 首次執(zhí)行完畢后Docker容器不會立即關閉,會等待一定時間周期,如果此時有新的請求進來,會被分配到該容器,直接運行代碼。
從執(zhí)行的原理也可看出,云函數(shù)理論上是支持無限自動擴容的。
冷啟動問題
由于serverless按量計費的特點,其實現(xiàn)機制就必須要在函數(shù)調(diào)用時才去啟動運行環(huán)境,也就是冷啟動問題。雖然保留一定時間可以讓后續(xù)的請求無需加載,但如果在極短時間內(nèi)并發(fā)大量請求,還是會同時啟動多個容器,影響首個請求的響應時間。前面也說到,云函數(shù)的特性和機制決定了它的應用場景,對于同時要求高并發(fā)、低時延的場景并不是特別適合。
對于冷啟動問題,下面以騰訊云的 云函數(shù)SCF 為例進行驗證。使用Postman的批量測試功能(Collection Runner)對云上部署的一個hello world函數(shù)進行串行測試。

從圖中可以看出,一段時間內(nèi)的首次請求耗時會比其他請求的耗時高出一個數(shù)量級。
冷啟動優(yōu)化
冷啟動的優(yōu)化主要針對同步的請求,首先分析下冷啟動耗時的組成,主要是容器的拉起和代碼的下載(當然也有資源調(diào)度和網(wǎng)絡配置等,這里暫不討論)。
1. 代碼緩存 :可以設計多級緩存,比如在宿主機上進行代碼包緩存,以及在可用區(qū)(AZ)內(nèi)部進行緩存,這樣后續(xù)的首次啟動就可以快速就近獲取,而無需再次從對象存儲下載。
2. 容器預創(chuàng)建 :一個優(yōu)化思路就是預加載,也就是預測將會到來的請求,提前拉起容器實例,從而減少耗時。有以下幾種可能的方案:
- 進行請求量的 實時計算 ,如果請求呈上升趨勢,就開始預創(chuàng)建容器實例,同理下降則進行回收。
- 云函數(shù)調(diào)用鏈: 這是一種可確定的預測,當云函數(shù)之間出現(xiàn)互相調(diào)用,在前面的函數(shù)被觸發(fā)時就可以同時預創(chuàng)建調(diào)用鏈后面的實例;
- 版本更新: 如果函數(shù)版本進行更新,則之后的所有請求都會重新冷啟動,為了避免這種情況,需要預創(chuàng)建一些實例并下載新版本代碼,之后才能將流量平滑遷移到新版本函數(shù)。
應用場景
下面介紹比較適合使用serverless技術的幾種場景。
1.rest API
利用云函數(shù)可以快速部署一個rest API應用,目前的云廠商基本都支持大部分node,Python和php的web框架,如koa、Express.js、Next.js、Flask、Django、Laravel等等。
這種web架構是前后端分離,即云函數(shù)中的后臺接口只提供數(shù)據(jù),頁面的渲染在瀏覽器進行。可以將前端的代碼部署到對象存儲中,并使用相關云數(shù)據(jù)庫作為數(shù)據(jù)存儲,這就成為一個完整的云上Full Stack應用。
2.SSR
SSR(Server-Side Rendering):后端渲染,即頁面直接在后臺進行渲染,瀏覽器只負責顯示。這種比較傳統(tǒng)的web架構很適合應用于serverless,只需將整個后端代碼部署到云函數(shù)即可,好處有:1.利于seo,2.降低系統(tǒng)復雜度,易于部署。
serverless很適合用于流量分布不均的輕量應用,比如一些活動頁面,可能一個周期內(nèi)只有很短的一段時間會有大量訪問,且需要長期的維護,此時為這個應用去購買高配置的服務器顯然是不劃算的。使用serverless之后則可以完全解決這個問題,按量計費降低了成本,既免去了長期運維又不需要擔心擴容問題。
3.任務執(zhí)行
云函數(shù)本身是無狀態(tài)的,所以天然適合無狀態(tài)任務,如果需要狀態(tài)存儲則需要借助BaaS層的組件。云函數(shù)的優(yōu)勢是可以與云提供商下的其他服務(比如數(shù)據(jù)庫、緩存、對象存儲、CDN、AI、轉(zhuǎn)碼等)打通,在函數(shù)中使用SDK連接各個組件(但這同樣意味著將在云產(chǎn)商綁定的道路上越走越遠)。以下是一些適用場景:
- 消息通知:比如觸發(fā)后向某個用戶發(fā)送郵件、短信等。
- 定時任務:云函數(shù)一般提供定時器觸發(fā),方便進行定時任務的執(zhí)行。
- CDN自動刷新:一般來說會把圖片、網(wǎng)頁等靜態(tài)資源存到對象存儲,并且配置CDN加速,一旦資源發(fā)生修改還得手動進行CDN刷新預熱。可以使用對象存儲上傳的事件觸發(fā)器,在云函數(shù)中調(diào)用CDN接口自動化刷新預熱。
- 視頻轉(zhuǎn)碼:如果云產(chǎn)商提供轉(zhuǎn)碼服務,可以借助云函數(shù)很方便的完成轉(zhuǎn)碼任務。如原視頻上傳到對象存儲后,該事件可以觸發(fā)云函數(shù)調(diào)用轉(zhuǎn)碼服務,并將轉(zhuǎn)碼后的視頻發(fā)布到對象存儲中,如果使用了CDN還可以進行緩存刷新。
- AI服務:可以使用云函數(shù)調(diào)用該產(chǎn)生的AI服務,比如調(diào)用OCR接口識別圖片文字內(nèi)容后返回。
- Devops:例如將Github的webhook設置為云函數(shù)的地址,當代碼提交后觸發(fā)云函數(shù),執(zhí)行CI/CD任務,構建后發(fā)布產(chǎn)物到云服務器上。