一、什么是Serverless?
1、Serverless技術(shù)簡介
? Serverless(無服務(wù)器架構(gòu))指的是由開發(fā)者實現(xiàn)的服務(wù)端邏輯運(yùn)行在無狀態(tài)的計算容器中,它由事件觸發(fā), 完全被第三方管理,其業(yè)務(wù)層面的狀態(tài)則被開發(fā)者使用的數(shù)據(jù)庫和存儲資源所記錄。
? Serverless使得開發(fā)者無需直接處理服務(wù)器(無論是物理機(jī),虛擬機(jī),容器等)。無主機(jī)的優(yōu)勢會讓使用者在服務(wù)器維護(hù)方面的操作開銷大大減少,無需為升級服務(wù)器而憂心,無主機(jī)還意味著在應(yīng)用程序中需要監(jiān)控的度量指標(biāo)也會不同。這是因為使用的大多數(shù)底層服務(wù)不會再發(fā)布 CPU、內(nèi)存、磁盤大小等傳統(tǒng)度量指標(biāo)了。這讓不再需要再特別關(guān)心架構(gòu)的底層操作細(xì)節(jié)。
? AWS云架構(gòu)戰(zhàn)略副總裁Adrian Cockcroft曾經(jīng)針對Serverless的界定給出了一個簡單的方法:“如果你的PaaS能夠有效地在20毫秒內(nèi)啟動實例并運(yùn)行半秒,那么就可以稱之為Serverless”。而在 A Berkeley View on Serverless Computing 論文中的描述:Serverless = FaaS + BaaS 。
? 參考上面關(guān)于Serverless架構(gòu)的技術(shù)邏輯示意圖,可以看到Serverless架構(gòu)大量依賴第三方服務(wù)(也叫做后端即服務(wù),即“BaaS”)或暫存容器中運(yùn)行的自定義代碼(函數(shù)即服務(wù),即“FaaS”)的應(yīng)用程序,因此FaaS和BaaS可以視作Serverless的兩個具體實現(xiàn)。函數(shù)是無服務(wù)器架構(gòu)中抽象語言運(yùn)行時的最小單位。在這種“按需使用”的架構(gòu)中,并不看重運(yùn)行一個函數(shù)需要多少 CPU 或 RAM 或任何其他資源,而是更看重運(yùn)行函數(shù)所需的時間,也只為這些函數(shù)的運(yùn)行時間付費(fèi)。
下面簡要分析Serverless所具備的優(yōu)勢,以及目前存在的一些短板:
? Serverless 架構(gòu)所具備的優(yōu)勢有:
- 更快的開發(fā)速度:相較于IaaS和PaaS,基于Serverless技術(shù)的FaaS平臺通過將傳統(tǒng)應(yīng)用運(yùn)行過程中的客戶業(yè)務(wù)代碼邏輯部分抽象提煉出來(形成 用戶函數(shù)代碼 + BaaS的格局),開發(fā)者只需要按照云平臺標(biāo)準(zhǔn)開發(fā)函數(shù)集合,開發(fā)者不需要關(guān)心底層使用什么框架——只需要開發(fā)業(yè)務(wù)邏輯;更不知道有多少個實例在運(yùn)行、運(yùn)行在哪里,這些都使得開發(fā)者能將更多的精力專注于業(yè)務(wù)代碼。
- 內(nèi)建自動化部署:Serverless 架構(gòu)通常通過在平臺上提供的 API 以及各種工具,實現(xiàn)內(nèi)建的自動化部署。一般來說,這些工具可以監(jiān)聽源代碼倉庫的變更,并在代碼更新時自動部署到生產(chǎn)環(huán)境。在部署過程中,工具會把代碼打包成一個或多個函數(shù),并將其上傳到 FaaS 平臺,然后將其配置為適當(dāng)?shù)?URL 和事件觸發(fā)器,以響應(yīng)請求。這樣,每次請求都會觸發(fā)對應(yīng)的函數(shù)執(zhí)行,從而實現(xiàn)了代碼的實時部署。
- 減少資源開銷: 函數(shù)在沒有請求時,函數(shù)實例為0。當(dāng)有請求時,云平臺會快速拉起一個實例以承載流量。更重要的:函數(shù)可以按照請求計費(fèi),即調(diào)用一次就付費(fèi)一次,而傳統(tǒng)服務(wù)則是按照實例規(guī)格計費(fèi)。
? Serverless 架構(gòu)的一些短板:
- 狀態(tài)管理: 要想實現(xiàn)自由的縮放,無狀態(tài)是必須的,而對于有狀態(tài)的服務(wù),使用serverless這就喪失了靈活性,有狀態(tài)服務(wù)需要與存儲交互就不可避免的增加了延遲和復(fù)雜性。
- 計算環(huán)境高度標(biāo)準(zhǔn)化: 無服務(wù)計算應(yīng)用運(yùn)行所依托的底層服務(wù)器以及運(yùn)行環(huán)境對用戶是透明的,用戶無法選擇,也無法優(yōu)化。無服務(wù)計算程序運(yùn)行的環(huán)境是高度標(biāo)準(zhǔn)化的,有些依賴于特定運(yùn)行環(huán)境、特定服務(wù)器版本、甚至特定硬件資源的依賴較難確保兼容性。
- 本地測試:目前在使用Serverless架構(gòu)的開發(fā)過程中還缺少比較成熟的調(diào)試和開發(fā)工具。
- 冷啟動耗時
2、Serverless 關(guān)鍵技術(shù)
(1)事件驅(qū)動
? Serverless 的"運(yùn)行才計算“的特性,便意味著他是一種 “嚴(yán)格” 的事件驅(qū)動式計算。 事件驅(qū)動程序設(shè)計這種設(shè)計模型是在交互程序(Interactive program)的情況下孕育而生的。這也意味著,系統(tǒng)在編程模型上有著巨大的改變。在我們編寫 GUI 程序,如桌面程序、Web 前端應(yīng)用,我們都通過監(jiān)聽用戶對按鈕、鏈接等組件操作,才開始相應(yīng)的處理邏輯。這和 Serverless 是相似的,只在用戶使用的時候,才會對應(yīng)用戶的行為進(jìn)行響應(yīng)。
(2)容器技術(shù)
? 容器技術(shù)在 Serverless 架構(gòu)中通常是通過 Docker 實現(xiàn)的。云服務(wù)提供商會將每個函數(shù)的代碼打包到一個獨(dú)立的 Docker 容器中。在容器內(nèi)部,可以確保代碼可以在隔離的環(huán)境中運(yùn)行,并且不會影響其他函數(shù)或應(yīng)用程序的運(yùn)行。
? 當(dāng)請求到達(dá)時,云服務(wù)提供商會在容器內(nèi)部執(zhí)行函數(shù),并在完成后銷毀容器。這種做法有助于確保每個函數(shù)的執(zhí)行是短暫的,并且不會占用過多資源,從而避免了資源浪費(fèi)。
? 通過使用容器技術(shù),Serverless 架構(gòu)可以確保函數(shù)在隔離的環(huán)境中運(yùn)行,并且可以快速擴(kuò)展,以滿足增長的需求。同時,容器技術(shù)還可以提高應(yīng)用程序的安全性,因為可以限制函數(shù)的權(quán)限,以防止函數(shù)訪問不該訪問的數(shù)據(jù)。
3、與常見技術(shù)架構(gòu)對比
(1)傳統(tǒng)架構(gòu) -VS- Serverless
? 一個傳統(tǒng) Java Web應(yīng)用的技術(shù)架構(gòu)可能如下圖所示:
? 這樣的架構(gòu)可以讓前端十分輕便,不需要做什么應(yīng)用邏輯,只是負(fù)責(zé)渲染用戶界面,將請求通過HTTP發(fā)送給后端,而所有的數(shù)據(jù)操作都是有由后端的Java程序來完成的。這樣的架構(gòu)開發(fā)起來比較容易,但是維護(hù)起來確十分復(fù)雜,前端開發(fā)、后端的開發(fā)都需要十分專業(yè)的人員、環(huán)境的配置,還要有人專門維護(hù)數(shù)據(jù)庫、應(yīng)用的更新和升級。
? 而在serverless架構(gòu)中,我們不再需要在服務(wù)器端代碼中存儲任何會話狀態(tài),而是直接將它們存儲在NoSQL中,這樣將使應(yīng)用程序無狀態(tài),有助于彈性擴(kuò)展。前端可以直接利用BaaS而減少后端的編碼需求,這樣架構(gòu)的本質(zhì)上是減少了應(yīng)用程序開發(fā)的人力成本,降低了自己維護(hù)基礎(chǔ)設(shè)施的風(fēng)險,而且利用云的能力更便于擴(kuò)展和快速迭代。
(2)MicroService -VS- Serverless
? 微服務(wù)(MicroService)是軟件架構(gòu)領(lǐng)域業(yè)另一個熱門的話題。如果說微服務(wù)是以專注于單一責(zé)任與功能的小型功能塊為基礎(chǔ),利用模組化的方式組合出復(fù)雜的大型應(yīng)用程序,那么我們還可以進(jìn)一步認(rèn)為Serverless架構(gòu)可以提供一種更加“代碼碎片化”的軟件架構(gòu)范式,我們稱之為Function as a Services(FaaS)。而所謂的“函數(shù)”(Function)提供的是相比微服務(wù)更加細(xì)小的程序單元。例如,可以通過微服務(wù)代表為某個客戶執(zhí)行所有CRUD操作所需的代碼,而FaaS中的“函數(shù)”可以代表客戶所要執(zhí)行的每個操作:創(chuàng)建、讀取、更新,以及刪除。當(dāng)觸發(fā)“創(chuàng)建賬戶”事件后,將通過AWS Lambda函數(shù)的方式執(zhí)行相應(yīng)的“函數(shù)”。從這一層意思來說,我們可以簡單地將Serverless架構(gòu)與FaaS概念等同起來。
? Serverless 天生就與微服務(wù)架構(gòu)是相輔相成的。一個 Serverless 應(yīng)用擁有自己的網(wǎng)關(guān)、數(shù)據(jù)庫、接口,你可還以使用自己喜歡的語言(受限于服務(wù)提供者)來開發(fā)服務(wù)。換句話來說,在這種情形下,一個 Serverless 可能是一個完美的微服務(wù)實例。
(3)Serverful Cloud -VS- Serverless Cloud
? 傳統(tǒng)云平臺與Serverless平臺三個比較關(guān)鍵的區(qū)別是:
- **解耦的計算和存儲。**存儲和計算分別擴(kuò)展,并獨(dú)立調(diào)配和定價。通常,存儲由單獨(dú)的云服務(wù)提供,計算是無狀態(tài)的。
- **執(zhí)行代碼而不管理資源分配。**用戶提供一段代碼而不是請求資源,云自動提供資源來執(zhí)行該代碼。
- 按使用的資源而不是分配的資源的比例支付。計費(fèi)是根據(jù)與執(zhí)行相關(guān)的某個維度(如執(zhí)行時間)進(jìn)行的,而不是根據(jù)基礎(chǔ)云平臺的某一維度(如分配的VM的大小和數(shù)量)進(jìn)行的。
? 傳統(tǒng)云平臺與Serverless平臺的其他技術(shù)細(xì)節(jié)的一些對比(以AWS為例):
4、Serverless業(yè)界工程實踐
- AWS Lambda :AWS Lambda云計算服務(wù)介紹_如何使用AWS Lambda-AWS云服務(wù) (amazon.com)
- 阿里云函數(shù)計算平臺: 函數(shù)計算FC_無服務(wù)器計算_Serverless_容器與中間件-阿里云 (aliyun.com)
- 開源 FaaS平臺
- 等等
二、FaaS
1、IaaS -> CaaS -> PaaS -> FaaS
-
IaaS (Infrastructure as a Service): 基礎(chǔ)設(shè)施即服務(wù)。 是指提供基礎(chǔ)設(shè)施(如計算、存儲、網(wǎng)絡(luò)等)作為服務(wù),用戶可以在此基礎(chǔ)上搭建自己的應(yīng)用環(huán)境。
-
CaaS (Containers as a Service): 容器即服務(wù)。 是指將容器技術(shù)提供給用戶使用,用戶可以通過容器運(yùn)行自己的應(yīng)用。
-
PaaS (Platform as a Service): 平臺即服務(wù)。 是指提供開發(fā)平臺和應(yīng)用管理工具,用戶只需要關(guān)注應(yīng)用的開發(fā)和運(yùn)行,不需要關(guān)注底層的基礎(chǔ)設(shè)施。
-
Serverless:無服務(wù)器架構(gòu)。 是指不需要為了運(yùn)行應(yīng)用程序而顯式管理和配置服務(wù)器資源,所有的底層管理和維護(hù)都由平臺提供方負(fù)責(zé)。用戶只需要上傳自己的代碼,等待代碼被自動運(yùn)行即可。 Serverless = FaaS + BaaS。BaaS (backend as a service)
-
FaaS (Function as a Service) 函數(shù)即服務(wù): 作為一種云計算服務(wù),它允許開發(fā)人員在云提供商處部署單個函數(shù),而不是整個應(yīng)用程序。云提供商在請求到達(dá)時自動執(zhí)行函數(shù),并在請求完成后自動銷毀。而“FaaS”中 最關(guān)鍵的 "F"也就是函數(shù)是如何定義的呢?可以參考下面OpenFaaS項目發(fā)起人 Alex 對CloudFunction的定義:
2、FaaS 關(guān)鍵技術(shù)
? 下面簡單探討一些 FaaS 中不得不面對的關(guān)鍵技術(shù)解決方案:
(1)彈性伸縮 (K8s 作為編排底座)
? 彈性伸縮是函數(shù)計算成本優(yōu)化中的關(guān)鍵一環(huán),彈性伸縮針對的主要對象是函數(shù)實例(一些faas架構(gòu)還包含一同啟動的MQ觸發(fā)器實例)。彈性伸縮的主要流程包含 : 指標(biāo)感應(yīng)(觸發(fā)彈性伸縮) -> 調(diào)度伸縮策略的計算 -> 最終擴(kuò)縮生效,以上步驟和k8s 的 HPA 十分類似,但是實現(xiàn)機(jī)制針對函數(shù)計算的特性有所改變,盡管如此,k8s目前所具備的能力也能較為有效地滿足FaaS的彈性伸縮需求,因此,開源社區(qū)的Serverless/FaaS產(chǎn)品基本是基于k8s實現(xiàn)的,也正是因為k8s的發(fā)展,促進(jìn)了開源社區(qū)的Serverless/FaaS產(chǎn)品的發(fā)展。
? 以下是 開源項目OpenFaaS基于k8s實現(xiàn)的架構(gòu)圖:
? 關(guān)于彈性伸縮,除了Kubernetes的HPA外,社區(qū)內(nèi)還有諸如事件驅(qū)動架構(gòu)彈性框架KEDA、以及KPA(Knative實現(xiàn))等。KEDA,其解決的核心問題是在事件驅(qū)動架構(gòu)下的彈性伸縮(事件觸發(fā)擴(kuò)縮容)與實例從0 -> 1、1->0的問題,KEDA充當(dāng)Kubernetes Mertrics Server工作,允許用戶使用專門的Kubernete自定義資源定義來定義自動縮放規(guī)則。
? KEDA可以在云和邊緣上運(yùn)行,并且可與與Kubernetes組件(如Horizontal Pod Autoscaler)本地集成,并且沒有外部依賴關(guān)系。,KEDA整體架構(gòu)如下:
(2)函數(shù)Runtime & 函數(shù)加載機(jī)制
? FaaS 運(yùn)行時應(yīng)該為函數(shù)的執(zhí)行提供資源和安全隔離的語言運(yùn)行環(huán)境,并為函數(shù)傳遞調(diào)用事件,上下文信息和響應(yīng)信息等。函數(shù)運(yùn)行時應(yīng)該為需要具備統(tǒng)一的接口規(guī)范來支持多語言的接入,以及專門的監(jiān)控管理組件(類似隨函數(shù)實例一同啟動的Agent)來維護(hù)函數(shù)實例的生命周期。
? 以 業(yè)界成熟的 FaaS 平臺AWS的Lambda為例,其函數(shù)運(yùn)行時架構(gòu)就類似下圖所示:右側(cè)虛線框括起來的即為一個函數(shù)實例,包含一個RuntimeAgent( 即API Endpoints) 用于處理函數(shù)調(diào)用過程中對函數(shù)進(jìn)程的監(jiān)控和管理,并收集執(zhí)行數(shù)據(jù)上傳函數(shù)實例外 HostAgent(Lambda Service)用于分析和記錄;Processes則包含了執(zhí)行用戶業(yè)務(wù)邏輯的函數(shù)進(jìn)程以及由FaaS平臺提供的Runtime環(huán)境。
? Lambda通過Runtime 以及 Runtime API來支持多種語言。Runtime API與Runtime之間通過API規(guī)范進(jìn)行調(diào)用,而用戶函數(shù)只需實現(xiàn)Runtime的特定接口函數(shù)即可完成初始化、加載和調(diào)用等操作。此外,Runtime提供了一個特定于語言的環(huán)境,用于在Lambda和函數(shù)之間傳遞調(diào)用事件、上下文信息和響應(yīng)。用戶可以使用Lambda平臺提供的Runtime,也可以構(gòu)建自己的運(yùn)行時。
? 每個主要編程語言版本都有一個單獨(dú)的運(yùn)行時,具有唯一的運(yùn)行時標(biāo)識符,如python3.10或nodejs18.x。要將函數(shù)配置為使用新的主要語言版本,需要更改運(yùn)行時標(biāo)識符。由于AWS Lambda無法保證主要版本之間的向后兼容性,因此這是一項客戶自主的操作。
? 對于定義為容器鏡像的函數(shù),可以在創(chuàng)建容器鏡像時選擇運(yùn)行時和Linux發(fā)行版。若要更改運(yùn)行時,需要更新函數(shù)的配置,并創(chuàng)建一個新的容器鏡像。運(yùn)行時與一個Amazon Linux發(fā)行版配對。底層執(zhí)行環(huán)境提供了額外的庫和環(huán)境變量,這樣可以從函數(shù)代碼中訪問這些庫和變量。
在k8s集群中,整個 Execution Enviroment 函數(shù)實例則可以作為一個Pod 運(yùn)行在特定集群中,與k8s其他組件組件或用戶自定義組件進(jìn)行交互。
? 以上可以看到Lambda 通過統(tǒng)一打包用戶函數(shù)以及函數(shù)運(yùn)行時為鏡像的方式實現(xiàn)了函數(shù)加載,此外,也可以通過掛載目錄或者共享內(nèi)存的方式實現(xiàn)用戶函數(shù)代碼加載,在此不做展開。
(3)冷啟動

? 冷啟動是指用戶函數(shù)實例從調(diào)度到啟動到能夠提供服務(wù)的準(zhǔn)備階段。我們來看看在傳統(tǒng)k8s集群中啟動一個包含用戶函數(shù)以及函數(shù)運(yùn)行時的鏡像容器需要包含幾個步驟:
- 申請調(diào)度函數(shù)資源,kube-scheduler 根據(jù)需求和現(xiàn)有資源計算,指定調(diào)度節(jié)點。
- 指定節(jié)點 kubelet 進(jìn)程監(jiān)測到了調(diào)度到該節(jié)點pod,調(diào)用容器運(yùn)行時,從 registry 去拉取鏡像。
- 低層容器運(yùn)行時拉起容器,注冊 k8s endpoint并進(jìn)行健康檢測(每1s一次)
- 健康檢查通過,容器在集群中初始化成功。
- (容器內(nèi)部:函數(shù)運(yùn)行時、函數(shù)實例、RuntimeAgent等完成初始化以及函數(shù)注冊)
? 其中鏡像拉取時間是不可控的,從幾秒鐘到幾十秒甚至數(shù)分鐘都有可能,在函數(shù)代碼包含在鏡像中的情況下,由于函數(shù)鏡像的異構(gòu)化,且由于存在大量的函數(shù)鏡像 故而導(dǎo)致難以復(fù)用。其次,kubelet創(chuàng)建容器的時間一般也長達(dá)數(shù)秒,最后容器啟動后,容器內(nèi)部的函數(shù)進(jìn)程啟動時間(包括運(yùn)行時環(huán)境啟動、依賴準(zhǔn)備等)也需要耗費(fèi)時間。
? 綜上,函數(shù)冷啟動時延是FaaS中的一個關(guān)鍵問題,針對冷啟動優(yōu)化目前業(yè)界大概有以下方法:
-
針對鏡像拉取時延,可以采取鏡像代碼分離的方法,鏡像本身是分層的,故所以可將用戶函數(shù)代碼 與 函數(shù)運(yùn)行時、RuntimeAgent等環(huán)境依賴層分離,節(jié)點提前將不變化的那部分內(nèi)容提前拉取,節(jié)省時間。
-
針對拉起容器,以及拉起容器后容器內(nèi)部的函數(shù)運(yùn)行時、RuntimeAgent等環(huán)境以及組件啟動帶來的時間損耗,可以通過函數(shù)實例預(yù)熱,即維護(hù)一個冷啟動資源池的方式來降低時延,F(xiàn)aaS平臺可以預(yù)先維護(hù)一批不包含業(yè)務(wù)函數(shù)的基礎(chǔ)容器組成一個冷啟動資源池,待到冷啟動過程中,再與某個用戶函數(shù)實例綁定,通過**共享存儲卷 **或 直接在線拉取代碼 等方式加載用戶函數(shù)實例,并開始提供服務(wù)。冷啟動池的容量、擴(kuò)縮容等配置則由FaaS平臺進(jìn)行統(tǒng)一的監(jiān)控和管理。(或者采用更輕量高效的容器運(yùn)行時:一個是基于KVM的輕量級虛擬化技術(shù),如Firecracker;另一個則是Wasm。AWS的Lambda底層技術(shù)就是使用了Firecracker,他的冷啟動時間都是ms級的)
-
針對健康檢查,OpenFaaS 曾嘗試過在K8s健康檢查前,通過 RuntimeAgent(watchdog) 提前開始接受并處理外界流量的方式來降低時延,但這種方法有許多問題,暫不推薦。
-
針對容器內(nèi)部用戶業(yè)務(wù)函數(shù)進(jìn)程實例啟動的耗時,可以參考 OpenFaaS 的在維護(hù)一個緩存函數(shù)實例的情況下,在容器內(nèi)Fork a Processe Per Request的方式。
? 此外,一般FaaS要求能做到函數(shù)實例實例流量為0的情況下縮容至0(K8s 原生的 HPA暫時做不到這一點,但KEDA可以),但一些faas平臺并未對此做強(qiáng)制限制,比如OpenFaaS開源版默認(rèn)運(yùn)行一個函數(shù)實例來承載初始流量,其他的一些平臺則采取了維護(hù)冷啟動資源池的方式來避初始化過長的問題。
(4)函數(shù)的調(diào)用/觸發(fā)方式
-
基于Web函數(shù)架構(gòu):其本質(zhì)是通過HTTP方式來調(diào)用函數(shù)。這里核心在于函數(shù)實例的Runtime環(huán)境需要提供一個Web框架和Web Server,請求進(jìn)入Runtime后則調(diào)用用戶函數(shù)。每一個函數(shù)默認(rèn)配置一個HTTP觸發(fā)器并為其分配一個固定的獨(dú)立域名,只要請求這個域名就能夠以HTTP觸發(fā)函數(shù)執(zhí)行,函數(shù)只要實現(xiàn)對應(yīng)接口即可處理請求,最后再通過FaaS平臺提供的API網(wǎng)關(guān)對函數(shù)實例接口請求進(jìn)行集中的處理。
-
基于事件驅(qū)動架構(gòu):不管是社區(qū)還是公有云的產(chǎn)品,都有觸發(fā)器的概念。所謂的觸發(fā)器其實就是事件源,事件源可以由一個統(tǒng)一的Sidecar容器接收然后以HTTP調(diào)用函數(shù);也可以由每個函數(shù)Runtime直接接收后調(diào)用函數(shù)。
-
基于消息隊列MQ: MQ消費(fèi)是業(yè)務(wù)場景中常見的一種業(yè)務(wù)類型,無論是 離線的數(shù)據(jù)計算,還是在線的實時消息,都會選擇MQ作為中間件來對業(yè)務(wù)進(jìn)行異步處理和解耦,因此MQ消息隊列可以作為整個FaaS平臺最大的流量入口。
-
用戶自定義的觸發(fā)方式: 如OpenFaaS的名為Connector的組件可以讓開發(fā)者自定義函數(shù)的觸發(fā)方式。
(5)其他
? 下面是我個人整理的一些FaaS涉及技術(shù)點,可能不是很全,僅供參考。
3、云原生 FaaS 框架
(1) OpenFunction
? OpenFunction 是一個現(xiàn)代化的云原生 FaaS(函數(shù)即服務(wù))框架,它引入了很多非常優(yōu)秀的開源技術(shù)棧,包括 Knative、Tekton、Shipwright、Dapr、KEDA 等,這些技術(shù)棧為打造新一代開源函數(shù)計算平臺提供了無限可能:
- Shipwright 可以在函數(shù)構(gòu)建的過程中讓用戶自由選擇和切換鏡像構(gòu)建的工具,并對其進(jìn)行抽象,提供了統(tǒng)一的 API;
- Knative 提供了優(yōu)秀的同步函數(shù)運(yùn)行時,具有強(qiáng)大的自動伸縮能力;
- KEDA 可以基于更多類型的指標(biāo)來自動伸縮,更加靈活;
- Dapr 可以將不同應(yīng)用的通用能力進(jìn)行抽象,減輕開發(fā)分布式應(yīng)用的工作量。
(2) OpenFaaS
? OpenFaaS是一個發(fā)展比較久的FaaS開源項目,在GitHub上獲得了比較多的關(guān)注,它在CloudFunction運(yùn)行時處理請求的模式方面作了較多的探索。在本篇的第三節(jié)FaaS實踐中著重介紹。
(3) Knative:Home - Knative
? Knative 是一個開源的、基于 Kubernetes 的平臺,旨在簡化和加速容器化應(yīng)用程序的開發(fā)、部署和管理過程。它提供了一組構(gòu)建塊和工具,幫助開發(fā)人員將現(xiàn)代化的、云原生的應(yīng)用程序部署到 Kubernetes 集群上,實現(xiàn)無服務(wù)器架構(gòu)(Serverless)和自動化的容器編排。
三、FaaS實踐 - OpenFaaS
1、概覽
(1)是什么
? OpenFaaS 是一個開源的 FaaS 框架,可以讓用戶在其上部署和運(yùn)行自己的函數(shù)。OpenFaaS 使用 Docker 容器作為底層技術(shù),可以運(yùn)行在任何云環(huán)境或者私有云上。OpenFaaS 項目旨在將 Kubernetes 集群或者獨(dú)立的虛擬機(jī)等低級基礎(chǔ)設(shè)施轉(zhuǎn)化為管理無服務(wù)器函數(shù)的高級平臺。
(2)做了什么
- 函數(shù)調(diào)起:WatchDog 是OpenFaaS用于調(diào)起和監(jiān)控 Cloud Function 的關(guān)鍵實現(xiàn),其充當(dāng)運(yùn)行函數(shù)和微服務(wù)的反向代理。它可以獨(dú)立使用,也可以作為OpenFaaS容器的EntryPoint,并作為"Init Process" 在函數(shù)容器中啟動。其內(nèi)置了一個使用Golang實現(xiàn)的 HttpServer,提供并發(fā)請求、超時和運(yùn)行狀況檢查等功能。其通過加載各種環(huán)境變量讓開發(fā)者可以自定義其功能。
- 自動伸縮: OpenFaaS使用自主設(shè)計的 AutoScaler 進(jìn)行函數(shù)的自動伸縮。
- 冷啟動: OpenFaaS 在架構(gòu)設(shè)計中有側(cè)重,OpenFaaS 沒有維護(hù)冷啟動池然后按需加載業(yè)務(wù)代碼這種機(jī)制,它希望保持只讀模式的文件系統(tǒng),容器載體被設(shè)計成不可變的單元來獲得可預(yù)測的生命周期和獲取最大程度的安全性。所以 OpenFaaS 在無流量情況下沒有將函數(shù)實例數(shù)默認(rèn)縮零,只是作為一個可選配置針對函數(shù)粒度進(jìn)行開啟,整體的冷啟動數(shù)據(jù)流量期望通過最小的實例來進(jìn)行承載,最大程度地規(guī)避拉起一個新實例所需要的資源調(diào)度、二進(jìn)制拉取、進(jìn)程啟動、健康檢測這些流程產(chǎn)生的巨大冷啟動開銷。
(3)怎么用
? Overview - OpenFaaS
? OpenFaaS 通過helm 在原生K8s部署
2、關(guān)鍵技術(shù)構(gòu)成
? OpenFaaS 技術(shù)概覽圖:
上圖是 OpenFaaS 的抽象服務(wù)流程,下面是各個節(jié)點的簡單介紹:
? Gateway: HTTP 網(wǎng)關(guān),用于接收用戶請求及內(nèi)部指令。
? NATS Streaming: 用于異步執(zhí)行函數(shù)。
? Prometheus/ AlertManager: 用于收集服務(wù)指標(biāo)及擴(kuò)縮容操作。
? faas-netes: 針對 K8S 的 Provider,可以定制其他的 Provider 例如 Docker Swarm 等。
? Docker Registry: 用于拉取函數(shù)鏡像的倉庫。
(1)WatchDog
? WatchDog 是OpenFaaS用于調(diào)起和監(jiān)控 Cloud Function 的關(guān)鍵實現(xiàn),最新的of-watchdog充當(dāng)運(yùn)行函數(shù)或微服務(wù)的反向代理。它可以獨(dú)立使用,也可以作為OpenFaaS容器的EntryPoint,并作為"Init Process" 在函數(shù)容器中啟動。其內(nèi)置了一個使用Golang實現(xiàn)的 HttpServer,提供并發(fā)請求、超時和運(yùn)行狀況檢查等功能。其通過加載各種環(huán)境變量讓開發(fā)者可以自定義其功能。 OpenFaaS先后推出了 ClassicWatchdog 以及 of - Watchdog兩種 Watchdog模式。下面分別介紹:
- 經(jīng)典 WatchDog 工作模式:
這種模式下,watchdog 啟動了監(jiān)聽在 8080 端口的輕量級 HTTP 服務(wù)器,每個進(jìn)來的請求都會:
- 讀取請求頭和請求體
- fork 或者 exec 包含實際函數(shù)的可執(zhí)行文件
- 將請求頭和請求體寫入到函數(shù)進(jìn)程的 stdin
- 等待函數(shù)進(jìn)程的退出(或者超時)
- 讀取函數(shù)進(jìn)程的 stdout 和 stderr
- 在 HTTP 響應(yīng)中將去讀的字節(jié)發(fā)送回調(diào)用方
上述邏輯類似于傳統(tǒng)的 通用網(wǎng)關(guān)接口(CGI)。一方面,每次函數(shù)調(diào)用都啟動單獨(dú)的進(jìn)程看起來不夠高效,而另一方面,它確實很方便,因為 任何使用 stdio流進(jìn)行 I/O 處理的程序(包括 CLI 工具)都可以部署為 OpenFaaS 函數(shù)。
提起隔離,我們有必要區(qū)分下函數(shù) 和 調(diào)用:
- OpenFaaS 中的不同函數(shù)始終分布在不同的容器中
- 一個函數(shù)可以有一個或多個容器 —— 取決于縮放選項
- 同一函數(shù)的獨(dú)立調(diào)用可能會最終進(jìn)入同一個容器
- 同一函數(shù)的獨(dú)立調(diào)用將始終使用不同的進(jìn)程進(jìn)行
- 反向代理 Watchdog 工作模式:
? 如果 經(jīng)典 運(yùn)行時類似于 CGI,那么這個運(yùn)行時模式類似于后來的 FastCGI。運(yùn)行時希望在 watchdog 后面有一個長期運(yùn)行的 HTTP 服務(wù)器,而不是每次函數(shù)調(diào)用時創(chuàng)建新的進(jìn)程。這本質(zhì)上是 將 watchdog 組件變成反向代理:當(dāng)容器啟動時,反向代理 watchdog 也會創(chuàng)建一個監(jiān)聽在 8080 端口的輕量級 HTTP 服務(wù)器。然而,與 經(jīng)典 watchdog 不同的是反向代理watchdog 只創(chuàng)建一次函數(shù)的進(jìn)程,并將其當(dāng)成(長期運(yùn)行的)上游服務(wù)器。然后,函數(shù)調(diào)用轉(zhuǎn)變成到該上游的 HTTP 請求。
? 然而,反向代理模式并不為了取代經(jīng)典模式。經(jīng)典模式的強(qiáng)項在于其函數(shù)的編寫非常簡單。這也是沒有 HTTP 服務(wù)器的代碼的唯一選擇。比如使用 Cobol、bash 或者 PowerShell 腳本等等編寫的函數(shù)。
? 何時該使用反向代理運(yùn)行時模式:
- 函數(shù)需要在兩次調(diào)用之間保持狀態(tài):
- 緩存
- 持久連接(例如,保持從函數(shù)到數(shù)據(jù)庫的連接打開)
- 有狀態(tài)函數(shù)
- 每個函數(shù)啟動一個進(jìn)程可能開銷很大,為每個調(diào)用帶來了延遲
- 你想運(yùn)行一個(微)服務(wù)作為函數(shù)
根據(jù) OpenFaaS 的創(chuàng)建者 Alex Ellis 的解釋,FaaS,特別是 OpenFaaS,可以被視為在不依賴服務(wù)器抽象的情況下 部署微服務(wù)的簡化方式。即 FaaS 是無服務(wù)器架構(gòu)的規(guī)范示例。
因此,使用反向代理的方式,函數(shù)可以被看作是部署微服務(wù)的固執(zhí)的方式。方便、快速、簡單。但使用有狀態(tài)函數(shù)時,要留意由于多個調(diào)用可能在同一個進(jìn)程中結(jié)束而導(dǎo)致的警告:
- 在一個進(jìn)程中結(jié)束的并發(fā)調(diào)用可能會觸發(fā)代碼中的競爭條件(例如,一個帶有全局變量的 Go 函數(shù),而全局變量沒有鎖的保護(hù))。
- 在一個進(jìn)程中結(jié)束的后續(xù)調(diào)用可能會導(dǎo)致交叉調(diào)用數(shù)據(jù)泄露(當(dāng)然,就像傳統(tǒng)微服務(wù)一樣)。
- 由于該進(jìn)程在兩次調(diào)用之間被復(fù)用,因此代碼中的任何內(nèi)存泄漏都不會被釋放。
? wathdog 與 反向代理 watchdog 二者工作模式對比:
(2)APIGateway
Openfaas 網(wǎng)關(guān)為自定義函數(shù)提供 RESTful 風(fēng)格接口的外部路由,內(nèi)置 UI、faas-cli 和 API 請求均會由 Openfaas 網(wǎng)關(guān)進(jìn)行處理分發(fā)。
Openfaas 網(wǎng)關(guān)同時集成了 Prometheus 提供對函數(shù)和服務(wù)的監(jiān)控能力,也可調(diào)取 faas-provider 的 API 實現(xiàn)對容器的管理。
Faas-provider 是一個使用 go 語言實現(xiàn)的符合 Openfaas provider Http REST API 標(biāo)準(zhǔn)的 SDK 工具集。
OpenFaaS API Gateway主要職責(zé):
- 對函數(shù)的 CRUD 操作
- 代理函數(shù)調(diào)用服務(wù)
- 管理函數(shù)容器的擴(kuò)縮容
- 容器密鑰管理
- 日志引流
(3)FaaS-Provider模型 / faas-nets
? 參考閱讀:The power of interfaces in OpenFaaS (alexellis.io)
(3)Auto-Scaling
? 參考閱讀:Autoscaling - OpenFaaS 、Scale to Zero and Back Again with OpenFaaS
(4)基于NATS 的異步函數(shù)調(diào)用
? 下面兩張圖簡要闡述了同步/異步調(diào)用 上傳一份PDF文件函數(shù) 的調(diào)用過程,說明了如何通過NATS實現(xiàn)函數(shù)異步調(diào)用。
3、其他
(1)OpenFaaS開發(fā)者視角
拓展閱讀:
? - 對話阿里云叔同:如何看待 2022 年云原生的發(fā)展,2023 年有哪些值得關(guān)注的技術(shù)? - 掘金 (juejin.cn)文章來源:http://www.zghlxwxcb.cn/news/detail-630804.html
- 加州伯克利 Serverless View(berkeley view)文章來源地址http://www.zghlxwxcb.cn/news/detail-630804.html
到了這里,關(guān)于【云原生】Serverless 技術(shù)架構(gòu)分析的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!