- 華為Serverless核心技術與實踐
- 劉方明等
- 2057字
- 2022-05-06 18:20:00
1.4.4 函數工作流
本節將介紹典型商用平臺的函數工作流Lambda、Azure Durable Function及OpenWhisk Composer。
工作流(Workflow)是對工作流程及其各操作步驟之間業務規則的抽象及概括描述。在微服務架構下,通常會使用基于BPMN或更輕量化的工作流引擎來編排微服務,完成對業務流程的執行和監控等工作。當承載業務的單元從微服務變為函數時,同樣需要這樣的工作流引擎來編排函數,完成如下操作。
(1)順序調用函數。
(2)并行執行函數。
(3)分支執行函數。
(4)失敗重試,或者應用try/catch/finally。
函數工作流(也稱函數編排)當前有兩種形式:一種是以Step Function為代表的基于Markup標記語言(JSON)的工作流,與其相同的還有CNCF開源的Serverless Workflow規范(詳見Serverless Workflow官網);另一種是以Azure Durable Function、OpenWhisk Composer為代表的基于編碼實現的工作流形式。
1.4.4.1 基于JSON的函數工作流Step Function
函數的執行時間有上限,但是工作流引擎可以長時間運行任務,并保證執行過程的高可用,以及不丟失狀態數據。商用平臺如AWS提供了Step Function服務,支持在復雜業務場景下對函數及其他AWS服務進行編排。Step Function提供了可視化和基于配置文件(JSON)兩種編排方式。Step Function的執行過程用一個狀態機來實現,每個節點有7種不同的狀態類型,如表1-2所示。
表1-2 Step Function的狀態類型

工作流上的所有任務都是通過Task完成的,Task可以是一個Lambda函數,也可以是Activity(可長時間運行的任務)。

圖1-28 并行執行OCR識別的Step Function工作流視圖
圖1-28是一個并行執行后聚合(fork/join)的示例[4],旨在將圖片分給三個OCR提供者來并行識別,以獲取最可信的結果。并行state的output會將每個分支的輸出組合起來。下面是其實現的JSON代碼片段。


1.4.4.2 基于事件溯源編排的Azure Durable Function
Azure Durable Function的特點是通過函數編碼的方式實現了對函數工作流的支持。Durable Function包含三種函數,即編排(Orchestrator)函數、任務(Activity)函數和實體(Entity)函數,其中任務函數是承載業務邏輯的函數。
如圖1-29所示,Durable Function通過事件溯源的機制來保存編排函數的局部變量的狀態,從而保證事件重入后可以從記錄點繼續執行。它需要外部存儲服務來記錄工作流的歷史狀態及實例的狀態,配合完成整個編排過程。

圖1-29 Durable Function的編排依賴數據庫及消息隊列
Azure將常用的工作流總結為6種模式,而Durable Function完全支持這6種模式。
? 鏈式調用(函數順序調用):適用于需要順序工作流的場景,按順序去調用多個函數來完成完整的業務邏輯。
? 扇出/扇入(Fan-out/Fan-in):適用于并發執行多個函數后進行聚合的場景。
? 異步HTTP API:適用于外部客戶端查詢長時間運行的工作流運行狀態的場景。
? 監視:適用于在工作流的執行過程中,需要持續輪詢是否達到條件,然后執行下一步的場景。
? 人機交互:適用于工作流中需要人工干預的場景,比如人工審批。
? 聚合器:適用于需要將一個時間段內的多個事件聚合成單個實體數據的場景。
下面的代碼是Azure Durable Function官方文檔的一個函數鏈式調用的示例,編排函數順序調用F1~F4這4個函數,每一個輸出結果作為下一次調用的輸入。F1~F4是普通的Azure函數,在Durable Function中被視為Activity函數,承載具體的業務。Context.df可以按名稱調用函數,默認為異步調用,yield關鍵字則可以記錄檢查點。F1被調用后,編排函數退出,等到F1返回結果時,編排函數重入,獲得最后一個檢查點的結果,然后執行下一條代碼,以此類推。同樣,如果編排函數在執行過程中意外退出,函數實例重入時將從上一個yield調用處繼續執行。

Durable Function對編排函數的實現存在一些約束,要求代碼最好是冪等的,所以在編排函數的操作中要注意以下事項。
? 代碼不能依賴隨機數、當前的時間等。
? 不在編排函數中做I/O或自定義的線程調度。
? 不要在代碼中寫無限循環。
Durable Function在設計上對數據的持久性(Durability)更關注,不太適合關注性能的工作流,但其在數據訪問和函數編排上有自己的特色。
1.4.4.3 基于函數編排的OpenWhisk Composer
和Azure Durable Function類似,OpenWhisk自身支持Conductor Action的函數類型,這種函數可以完成函數編排,支持分支、順序等編排方式。如果Conductor函數在執行過程中調用了其他函數,那么該Conductor函數可以退出執行。例如,下面的Composer文檔中樣例Conductor函數代碼中的triple函數被調用并執行后,OpenWhisk系統將重新觸發Conductor函數,Conductor函數根據此時的狀態觸發下一個函數,直至Conductor函數的代碼全部執行完。和Durable Function使用事件溯源、依賴外部存儲服務的方式不同,OpenWhisk基本不依賴外部存儲服務。

基于Conductor函數,OpenWhisk抽象了一套編排的DSL接口,將其命名為Composer,用來支持函數編排中常用的順序、分支、fork/join等。在OpenWhisk系統中引入額外的Redis組件后,也可以支持長時間運行的編排任務。
下面這段Composer的編排代碼完成一個分支任務,如果通過身份驗證,則返回成功,否則返回失敗。這個編排函數在部署時,會被編譯并視為一個Conductor函數部署到OpenWhisk。

Composer的這種編排方式對開發者來說,學習成本很低;而對平臺的維護者來說,基于同一個系統支持函數及編排,也節省了維護的成本。
兩種工作流方式各有其適合的使用場景。Step Function類的編碼方式可以方便地進行可視化,對業務人員更友好。Durable Function類的編碼方式對開發者更友好。開發者可以根據實際的情況使用不同類型的工作流服務。
綜上所述,本節從平臺、框架、事件總線及函數工作流等維度介紹了典型的Serverless平臺及其生態發展。目前Serverless平臺雖然百花齊放,但距離成熟、標準化還有一定的差距,這也意味著Serverless方向有很多的創新機會,希望廣大開發人員抓住機遇、共同努力,投入新一代Serverless生態發展和產業建設的大潮之中。