Serverless Computing概念
????云原生計算基金會CNCF(Cloud Native Computing Foundation, CNCF)Serverless Whitepaper v1.0對無服務器計算作了如下定義:
Serverless computing refers to the concept of building and running applications that do not require server management. It describes a finer-grained deployment model where applications, bundled as one or more functions, are uploaded to a platform and then executed, scaled, and billed in response to the exact demand needed at the moment.
????無服務器計算(Serverless Computing)是指在構建和運行應用時無需管理服務器等基礎設施。它描述了一個更細粒度的部署模型,在該模型中,應用被拆解為一個或多個細粒度的函數(shù)被上傳到一個平臺,然后根據(jù)當前所需執(zhí)行、擴展和計費。
????無服務器計算并不意味著我們不再使用服務器來承載和運行代碼,也不意味著不再需要運維工程師。而是指無服務器計算的消費者不再需要花費時間和資源在服務器配置、維護、更新、擴展和容量規(guī)劃上。所有這些任務和功能都由無服務器平臺處理,并且完全從開發(fā)人員和IT/操作團隊中抽象出來。因此,開發(fā)人員專注于編寫應用程序的業(yè)務邏輯。運營工程師能夠將他們的重點提升到更關鍵的業(yè)務任務上。?
FaaS & BaaS
無服務器計算平臺可以提供以下一種或兩種服務:
1. FaaS(Functions-as-a-Service-函數(shù)即服務),通常提供事件驅動(event-driving)的計算。開發(fā)人員使用由事件(event)或HTTP請求觸發(fā)的函數(shù)運行和管理應用程序代碼。開發(fā)人員將小的代碼單元部署到FaaS,F(xiàn)aaS按需執(zhí)行和擴展,開發(fā)人員無需管理服務器或任何其他底層基礎設施。
2. Baas(Backend-as-a-Service后端即服務),是第三方基于API的服務,用于替換應用程序中的核心功能子集。因為這些API是作為一個自動擴縮容和透明操作的服務提供的,所以開發(fā)人員認為這是無服務器的 ,如:OSS
Pros & Cons
無服務器計算(Serverless Computing)應用利弊大致如下:
Pros:
1. 0服務器操作。無服務器通過消除維護服務器資源所涉及的開銷,極大地改變了運行軟件應用程序的成本模型。
2. 沒有配置、更新和管理服務器基礎結構。
3. 彈性伸縮:無服務器FaaS或BaaS產(chǎn)品可以立即精確地伸縮以處理每個單獨的傳入請求。對于開發(fā)人員來說,無服務器平臺沒有“預先計劃的容量”的概念,也不需要配置“自動伸縮”觸發(fā)器或規(guī)則。在沒有開發(fā)人員干預的情況下,自動進行縮放。在完成請求處理后,無服務器FaaS會自動縮小計算資源的規(guī)模,以確保永遠沒有空閑的容量。
4. 低成本。無服務器計算服務對空閑的虛擬機或容器不收費;也就是說當代碼沒有運行或沒有進行有意義的工作時,不收費。?
Cons:
1. 作為一種新興的計算模型、缺乏標準化和生態(tài)系統(tǒng)成熟度。
2. 由于運行時更具動態(tài)性,與iaas和paas相比,調試可能更具挑戰(zhàn)性。
3. 由于按需結構,如果運行時在空閑時刪除函數(shù)的所有實例,則某些無服務器運行時的“冷啟動”方面可能是性能問題。
4. 在更復雜的情況下(例如,觸發(fā)其他功能的功能),對于相同數(shù)量的邏輯,可以有更多的操作表面積。
Serverless處理模型(Serverless Processing Model)
CNCF白皮書對于無服務器框架中的函數(shù)用法,函數(shù)約束、生命周期、調用類型和所需的抽象等定義了規(guī)范,以便同一個函數(shù)可以一次性編碼,并在不同的無服務器框架中使用。?

FaaS解決方案概括為具有以下圖中所示的幾個關鍵元素:
1. 事件源(Event sources)-觸發(fā)器或流事件到一個或多個函數(shù)實例中
2. 函數(shù)實例(Function instances)-單個函數(shù)/微服務,可根據(jù)需求進行擴展
3. FaaS控制器(FaaS Controller)-部署、控制和監(jiān)視函數(shù)實例及其源
4. 平臺服務(Platform services?)-FaaS解決方案使用的通用集群或云服務(有時稱為后端即服務-BaaS)
CNCF函數(shù)相關規(guī)范
函數(shù)定義(Function Definition)
無服務器函數(shù)定義可以包含以下規(guī)范和元數(shù)據(jù),函數(shù)定義是特定于版本的:
1. 唯一ID
2. 名字
3. 描述
4. 標簽
5. 版本ID(和/或版本別名)
6. 版本創(chuàng)建時間
7. 上次修改時間(函數(shù)定義的)
8. 函數(shù)處理程序
9. 運行時語言
10. 代碼+依賴項或代碼路徑和憑據(jù)
11. 環(huán)境變量
12. 執(zhí)行角色和密鑰
13. 資源(所需的CPU、內存)
14. 執(zhí)行超時時間
15. 日志失?。ㄋ佬抨犃校?/p>
16. 網(wǎng)絡策略/vpc
17. 數(shù)據(jù)綁定(Metadata Binding)
元數(shù)據(jù)詳細信息(Metadata details)
1. 版本(Version)-每個函數(shù)版本都應該有一個唯一的標識符,此外,可以使用一個或多個別名(例如“最新”、“生產(chǎn)”、“測試版”)標記版本。API網(wǎng)關和事件源將流量/事件路由到特定的函數(shù)版本。
2. 環(huán)境變量(Environment Variables)-用戶可以指定將在運行時提供給函數(shù)的環(huán)境變量。環(huán)境變量也可以從機密和加密內容派生,或者從平臺變量派生(例如,kubernetes envvar定義)。環(huán)境變量使開發(fā)人員能夠控制函數(shù)行為和參數(shù),而無需修改代碼和/或重建函數(shù),從而獲得更好的開發(fā)人員體驗和函數(shù)重用。
3. 執(zhí)行角色(Execution Role)-該函數(shù)應在特定的用戶或角色標識下運行,該標識授予并審核其對平臺資源的訪問權限。
4. 資源(Resources)-定義功能所需的或最大的硬件資源,如內存和CPU。
5. 超時(Timeout)-指定函數(shù)調用在被平臺終止之前可以運行的最長時間。
6. 失敗日志(死信隊列)(Failure Log (Dead Letter Queue))-隊列或流的路徑,用于存儲失敗的函數(shù)執(zhí)行列表,并提供適當?shù)脑敿毿畔ⅰ?/p>
7. 網(wǎng)絡策略(Network Policy)-分配給功能的網(wǎng)絡域和策略(用于與外部服務/資源通信的功能)。
8. 執(zhí)行語義(Execution Semantics)-指定應如何執(zhí)行函數(shù)(例如,每個事件至少執(zhí)行一次、至多執(zhí)行一次、完全執(zhí)行一次)。
數(shù)據(jù)綁定(Data Bindings)
????一些無服務器框架允許用戶指定函數(shù)使用的輸入/輸出數(shù)據(jù)資源,這使開發(fā)人員能夠簡化、提高性能(在執(zhí)行之間保留數(shù)據(jù)連接,可以預取數(shù)據(jù)等)和更好的安全性(數(shù)據(jù)資源憑據(jù)是上下文的一部分,而不是代碼)。
????綁定數(shù)據(jù)可以是文件、對象、記錄、消息等形式,函數(shù)規(guī)范可以包括一組數(shù)據(jù)綁定定義,每個定義指定數(shù)據(jù)資源、其憑證和使用參數(shù)。數(shù)據(jù)綁定可以引用事件數(shù)據(jù)(例如,db鍵是從事件“用戶名”字段派生的),示例:https://docs.microsoft.com/azure/azure-functions/functions-triggers-bindings
函數(shù)約束(Function Requirements)
函數(shù)和無服務器運行時應該滿足的通用需求:
1. 函數(shù)必須與不同事件類的基礎實現(xiàn)分離
2. 可以從多個事件源調用函數(shù)
3. 每個調用方法不需要不同的函數(shù)
4. 事件源可以調用多個函數(shù)
5. 函數(shù)可能需要與底層平臺服務進行持久綁定的機制,這可能是跨函數(shù)調用。函數(shù)可能是短暫的,但如果需要在每次調用(例如在日志記錄、連接和裝載外部數(shù)據(jù)源的情況下)上都進行引導,則引導可能會很昂貴。
6. 每個函數(shù)可以用不同于同一應用程序中使用的其他函數(shù)的代碼語言編寫。
7. 函數(shù)運行時應盡可能減少事件序列化和反序列化開銷(例如,使用本機語言結構或有效的編碼方案)
函數(shù)調用類型(Function Invocation Types)
根據(jù)不同的用例,可以從不同的事件源調用函數(shù),例如:
1. 同步請求(Synchronous Request (Req/Rep)),例如http請求、grpc調用
????- 客戶機發(fā)出請求并等待立即響應。這是一個阻塞呼叫。
2. 異步消息隊列請求(pub/sub)(Asynchronous Message Queue Request),例如RabbitMQ, AWS SNS, MQTT, Email, Object (S3) change、計劃事件(如cron作業(yè))
????- 消息發(fā)布到交換并分發(fā)到訂閱服務器
? ? - 沒有嚴格的消息順序, 可一次處理
3. 消息/記錄流(Message/Record Streams):Kafka, AWS Kinesis, AWS DynamoDB Streams, Database CDC
? ? - 一組有序的消息/記錄(必須按順序處理)
? ? - 通常,一個流被分割到多個分區(qū)/碎片(partitions/shards?),每個碎片有一個worker(碎片使用者)
? ? - 流可以從消息、數(shù)據(jù)庫更新(日志)或文件(例如csv、json、parquet)生成。
? ? - 事件可以推送到函數(shù)運行時,也可以由函數(shù)運行時拉取。
4. 批處理作業(yè)(Batch Jobs),例如ETL作業(yè)、分布式深度學習、HPC模擬
? ? - 作業(yè)(Jobs)被調度或提交到隊列,并在運行時使用多個并行函數(shù)實例進行處理,每個實例處理工作集(任務)的一個或多個部分。
? ? - 當所有并行工作人員成功完成所有計算任務時,作業(yè)完成。

?
函數(shù)生命周期(Function LifeCycle)
函數(shù)部署管道(Function Deployment Pipeline)

函數(shù)生命周期:
1. 編寫代碼、提供規(guī)范和元數(shù)據(jù)
2. 獲取代碼和規(guī)范,編譯并將其轉化為一個工件(二進制代碼、包或容器鏡像)
3. 工件部署到一個集群上,控制器實體負責根據(jù)事件流量和/或實例上的負載調整函數(shù)實例的數(shù)量。
函數(shù)操作(Function Operations)
無服務器框架可能允許以下操作和方法定義和控制功能生命周期:
1. 創(chuàng)建(Create)-創(chuàng)建一個新函數(shù),包括其規(guī)范和代碼
2. 發(fā)布(Publish)-創(chuàng)建可部署在群集上的函數(shù)的新版本
3. 更新別名/標簽(Update Alias/Label [of a version])-更新版本別名
4. 執(zhí)行/調用(Execute/Invoke)-不通過事件源調用特定版本
5. 事件源關聯(lián)(Event Source association?)-將函數(shù)的特定版本連接到事件源
6. 獲取(Get)-返回函數(shù)元數(shù)據(jù)和規(guī)范
7. 更新(Update)-修改函數(shù)的最新版本
8. 刪除(Delete)-刪除一個函數(shù),可以刪除一個特定的版本或函數(shù)的所有版本
9. 清單(List)-顯示函數(shù)及其元數(shù)據(jù)的列表
10. 狀態(tài)獲取(get stats)-返回有關函數(shù)運行時使用情況的統(tǒng)計信息
11. 日志獲?。╣et logs)-返回函數(shù)生成的日志

關鍵步驟說明:
1. Create:在創(chuàng)建函數(shù)時,提供其元數(shù)據(jù)(稍后在函數(shù)規(guī)范中描述)作為函數(shù)創(chuàng)建的一部分,將對其進行編譯并可能發(fā)布。稍后可以啟動、禁用和啟用功能。功能部署需要能夠支持以下用例:
????- 事件流(Event streaming),在這種情況下,隊列中可能總是有事件,但是可能需要通過顯式請求暫停/恢復處理。
? ? - 熱啟動(Warm startup)-在任何時候具有最少實例數(shù)的函數(shù),例如,接收到的“第一個”事件具有熱啟動,因為該函數(shù)已經(jīng)部署并準備好服務于該事件(而不是在“傳入”事件第一次調用時部署該函數(shù)的冷啟動)。
2. Publish:用戶可以發(fā)布一個函數(shù),這將創(chuàng)建一個新版本(最新版本的副本),發(fā)布的版本可能會被標記/標記或有別名,請參閱下面的詳細信息。
3. 用戶可能希望為調試和開發(fā)過程直接執(zhí)行/調用函數(shù)(繞過事件源或API網(wǎng)關)。用戶可以指定調用參數(shù),如所需版本、同步/異步操作、詳細級別等。
4. 用戶可能希望獲得函數(shù)統(tǒng)計信息(例如調用次數(shù)、平均運行時間、平均延遲、失敗、重試次數(shù)等),統(tǒng)計信息可以是當前度量值或一系列值(例如存儲在Prometheus或云提供程序設施(如AWS Cloud Watch))。
5. 用戶可能希望檢索函數(shù)日志數(shù)據(jù)。這可以根據(jù)嚴重性級別和/或時間范圍和/或內容進行篩選。日志數(shù)據(jù)是每個函數(shù)的,它包括諸如函數(shù)創(chuàng)建和刪除、顯式錯誤、警告或調試消息等事件,還可以選擇函數(shù)的stdout或stderr。每次調用最好有一個日志條目,或者一種將日志條目與特定調用關聯(lián)的方法(以便更簡單地跟蹤函數(shù)執(zhí)行流)。
事件源(Event Source)
不同類型的事件源包括:
1. 事件和消息服務,例如:?RabbitMQ, MQTT, SES, SNS, Google Pub/Sub
2. 存儲服務,例如:S3, DynamoDB, Kinesis, Cognito, Google Cloud Storage, Azure Blob, iguazio V3IO (object/stream/DB)
3. 端點服務,例如:物聯(lián)網(wǎng)(IoT)、HTTP網(wǎng)關(HTTP Gateway)、移動設備、Alexa、Google Cloud Endpoints
4. 配置存儲庫,例如:Git, CodeCommit
5. 使用特定于語言的sdk的用戶應用程序
6. 定時事件-允許定期調用函數(shù)。
事件源到函數(shù)的關聯(lián)(Event Source to Function Association)
函數(shù)是由事件源觸發(fā)的事件調用的。函數(shù)和事件源之間有一個n:m映射。每個事件源可以用來調用多個函數(shù),一個函數(shù)可以由多個事件源觸發(fā)。事件源可以映射到函數(shù)的特定版本或函數(shù)的別名,后者提供了更改函數(shù)的方法,并部署了一個新版本,而不需要更改事件關聯(lián)。事件源也可以定義為使用同一函數(shù)的不同版本,定義應為每個函數(shù)分配多少流量。
在創(chuàng)建了一個函數(shù)之后,或者在以后的某個時間點,需要將事件源關聯(lián)起來,該事件源應該作為該事件的結果觸發(fā)函數(shù)調用。這需要一組操作和方法,例如:
1. 創(chuàng)建事件源關聯(lián)
2. 更新事件源關聯(lián)
3. 列出事件源關聯(lián)
函數(shù)輸入(Function Input)
函數(shù)輸入包括事件數(shù)據(jù)(event data)和元數(shù)據(jù)(metadata),并且可以包括一個上下文對象(context object)。
事件數(shù)據(jù)和元數(shù)據(jù)(Event data and metadata)
事件詳細信息應傳遞給函數(shù)處理程序,不同的事件可能具有不同的元數(shù)據(jù),因此函數(shù)需要能夠確定事件的類型并輕松解析通用和特定于事件的元數(shù)據(jù)。
將事件類與實現(xiàn)分離是可取的,例如:處理消息流的函數(shù)將工作相同,而不管流存儲是Kafka還是Kinesis。在這兩種情況下,它都將接收消息體和事件元數(shù)據(jù),消息可以在不同的框架之間路由。
事件可以包括單個記錄(例如,在請求/響應模型中),或者接受多個記錄或微批(例如,在流模式中)。
FaaS解決方案使用的常見事件數(shù)據(jù)和元數(shù)據(jù)示例:
- 事件類別
-?版本
-?事件ID
-?事件來源/來源
-?源識別
-?內容類型
-?消息體
-?時間戳
事件/記錄特定元數(shù)據(jù)的示例:
-?HTTP: 路徑、方法、頭、查詢參數(shù)
-?Message Queue:消息隊列:主題,標題
-?記錄流(Record Stream):表、鍵、op、修改時間、舊字段、新字段
事件源結構示例:
-?AWS Lambda:http://docs.aws.amazon.com/lambda/latest/dg/eventsources.html
-?Microsoft Azure?Functions:https://docs.microsoft.com/azure/azure-functions/functions-triggers-bindings
-?Google?Cloud Functions:https://cloud.google.com/functions/docs/concepts/events-triggers
有些實現(xiàn)將JSON作為向函數(shù)傳遞事件信息的機制來關注。這可能會增加高速函數(shù)(例如流處理)或低能耗設備(IOT)的大量序列化/反序列化開銷。在這些情況下,將本機語言結構或其他序列化機制視為選項可能是值得的。
函數(shù)上下文(Function Context)
當調用函數(shù)時,框架可能希望提供對跨多個函數(shù)調用的平臺資源或常規(guī)屬性的訪問,而不是將所有靜態(tài)數(shù)據(jù)放在事件中,或強制函數(shù)在每次調用時初始化平臺服務。
上下文作為一組輸入屬性、環(huán)境變量或全局變量傳遞。有些實現(xiàn)使用這三種方法的組合。
上下文示例:
-?函數(shù)名、版本、ARN
-?存儲限制(Memory Limit)
-?請求ID(Request ID)
-?云區(qū)(Cloud Region)
-?環(huán)境變量(Environment Variables)
-?安全密鑰/令牌(Security keys/tokens)
-?運行時/bin路徑(Runtime/Bin paths)
-?日志(Log )
-?數(shù)據(jù)綁定(Data binding)
一些實現(xiàn)使用日志對象初始化日志對象(例如,作為AWS中的全局變量或Azure中的部分上下文),用戶可以使用集成平臺工具跟蹤函數(shù)執(zhí)行。除了傳統(tǒng)的日志記錄之外,未來的實現(xiàn)可能會將計數(shù)器/監(jiān)視和跟蹤活動抽象為平臺上下文的一部分,以進一步提高功能的可用性。
數(shù)據(jù)綁定作為函數(shù)上下文的一部分,平臺根據(jù)用戶配置啟動到外部數(shù)據(jù)資源的連接,這些連接可以在多個函數(shù)調用中重用。
函數(shù)輸出(Function Output)
當函數(shù)退出時,它可以:
-?向調用者返回一個值(例如,在HTTP請求/響應示例中)
-?將結果傳遞到工作流中的下一個執(zhí)行階段
-?將輸出寫入日志
應該有一種確定的方法來知道函數(shù)是否通過返回的錯誤值或退出代碼成功或失敗。
函數(shù)輸出可以是結構化的(如HTTP響應對象)或非結構化的(如某些輸出字符串)。
無服務器函數(shù)工作流(Serverless Function Workflow)
在無服務器域中,用例(Use Case)屬于以下類別之一:
-?一個事件觸發(fā)一個函數(shù)
-?事件的和/或組合觸發(fā)一個函數(shù)
-?一個事件觸發(fā)順序或并行執(zhí)行的多個函數(shù)
-?函數(shù)的結果可能是另一個函數(shù)的觸發(fā)器
-?n個事件(i n和/或)觸發(fā)m個函數(shù),即事件函數(shù)交錯的工作流,如事件1觸發(fā)函數(shù)1,完成函數(shù)1和事件2以及事件3觸發(fā)函數(shù)2,然后函數(shù)2的不同結果觸發(fā)分支到函數(shù)3或函數(shù)4。
用戶需要一種方法來指定他們的無服務器用例或工作流。例如,一個用例可以是“在照片上傳到云存儲時在照片上進行人臉識別(發(fā)生照片存儲事件)?!绷硪粋€物聯(lián)網(wǎng)用例可以是“在接收到運動檢測事件時進行運動分析”,然后根據(jù)分析功能的結果,或者“觸發(fā)房屋警報并調用e警察部門“或只是”將運動圖像發(fā)送給房主?!坝嘘P詳細信息,請參閱用例部分。
AWS提供“步驟函數(shù)”(step function),供用戶指定其工作流,但步驟函數(shù)不允許指定觸發(fā)工作流中哪些函數(shù)的事件/事件。
下圖是涉及事件和函數(shù)的用戶工作流的示例。使用這種函數(shù)圖,用戶可以輕松地指定事件和函數(shù)之間的交互,以及如何在工作流中的函數(shù)之間傳遞信息。

?功能圖狀態(tài)包括:
- Event State(事件狀態(tài)):此狀態(tài)允許等待來自事件源的事件,然后觸發(fā)函數(shù)運行或多個函數(shù)按順序、并行或在分支中運行。
- Operation/Task State(操作/任務狀態(tài)):此狀態(tài)允許按順序或并行運行一個或多個函數(shù),而不等待任何事件。
-?Switch/Choice State(切換/選擇狀態(tài)):此狀態(tài)允許轉換到多個其他狀態(tài)(例如,前一個函數(shù)結果觸發(fā)分支/轉換到不同的下一個狀態(tài))。
-?End/Stop State(結束/停止狀態(tài)):此狀態(tài)以失敗/成功終止工作流。
-?Pass State(通過狀態(tài)):此狀態(tài)在兩個狀態(tài)之間插入事件數(shù)據(jù)。
-?Delay/Wait State(延遲/等待狀態(tài)):此狀態(tài)導致工作流執(zhí)行延遲指定的持續(xù)時間或直到指定的時間/日期。
狀態(tài)和相關信息需要保存在一些持久存儲中,以便進行故障恢復。在某些用例中,用戶可能希望將來自一個狀態(tài)的信息傳遞到下一個狀態(tài)。這些信息可以是函數(shù)執(zhí)行結果的一部分,也可以是與事件觸發(fā)器關聯(lián)的輸入數(shù)據(jù)的一部分。需要在每個狀態(tài)定義一個信息過濾器,以過濾出需要在狀態(tài)之間傳遞的信息。
參考
-?CNCF Serverless Whitepaper v1.0?