本文作者:史明偉 , 阿里雲智慧高階技術專家。
1 Serverless 非同步任務處理系統誕生和挑戰
無論是對於雲的開發者,還是嘗試業務升級的企業客戶,Serverless的三個概念 「極致彈性、無伺服器運維、 按需付費」 幾乎已經深入人心;但關於 Serverless能做什麼、怎麼做,卻仍然是圍繞在大家身邊最普遍的聲音。
在Serverless研發的初始階段,通常技術團隊會更多聚焦於彈性,冷啟動加速,希望通過彈效能力凸顯產品技術競爭力,確立產品在市場上的領先地位,並依賴這些能力吸引開發者和企業客戶使用Serverless,這個階段,更多的是依靠技術影響力引導大家探索 Serverless。
隨著我們對Serverless的不斷深入理解,同時彈效能力的提升進入深水區,相對來說沒有本質改變的情況下,我們將更多地思考觸及Serverless彈性以外的其他價值,這個時候,彈性將作為系統的基礎能力滲透在產品各個方面,需要更多的從系統性的角度考慮 Serverless能做什麼,能給客戶帶來什麼,如何讓業務聚焦那些不得不需要客製化化的部分?
系統性意味著我們需要從包括資源供給,彈性排程,應用框架,容量評估,運維觀測等多個維度來考慮Serverless系統對於客戶業務的價值, 哪些需要使用者參與,或者少參與,哪些需要以服務化能力提供給客戶;對於那些客戶必須參與的,平臺需要提供便利的開發工具滿足開發階段客戶需求;在具體業務邏輯實現中,利用Serverless的靈活擴充套件性,儘可能快速的幫助開發者實現和其他雲服務的快速連線,提供穩定高效存取是Serverless所能帶給客戶的核心價值。
面對實際的客戶需求,產品需要考慮多種業務場景: 離線場景的耗時任務執行,線上場景的高並行請求處理,以及事件驅動場景的事件處理,如何將眾多業務場景需求在一個計算平臺上得到滿足,是我們面臨的最大挑戰。
基於對 Serverless的不斷深入理解,結合產品在彈性排程方面的不斷積累,我們開始了基於多租架構的Serverless非同步任務處理系統的構建,利用非同步化的存取方式,幫助使用者託管請求,以服務化的手段幫助使用者快速執行任務,處理異常,提供可靠的執行保障,結合非同步化的結果投遞能力,希望能夠面向事件驅動,線上業務處理,Serverless Job/Task 等複雜業務場景,為客戶帶來更多價值。
構建一個面向多租場景的Serverless非同步任務處理系統需要面臨各種挑戰;這個時候我們需要化繁為簡,分析任務系統到底要做什麼:任務分發, 任務排程, 任務執行。
Serverless本質是一個多租分時複用的商業模式,關於Serverless非同步任務處理系統的挑戰,結合任務處理系統的功能需求,這些挑戰可以總結歸類為三個方面:
第一,多租架構本身帶來的挑戰:包括租戶隔離問題,多租資源管理,以及如何權衡隔離性和成本之間的矛盾,最後還需要關注多租架構下自動診斷,快速定位問題的挑戰;
第二,業務型別多樣性和資源供給之間的矛盾帶來的挑戰:資源需求多樣化,客戶可能需要多種資源,比如面向 CPU密集型、IO密集型、記憶體密集型等;執行環境多樣化,客戶執行業務邏輯時,需要為任務提供與其對應的執行環境,需要面對多種執行環境;執行時長不確定性,面對離線和線上場景的不同業務特徵,實際任務的執行時長差異巨大;最後,不同業務型別流量特徵不同,流量不可預知等問題帶來的請求處理,任務排程和流控策略方面的挑戰;
第三,任務管理本身需要面臨的挑戰:包括任務生命週期管理,執行操作、 任務去重,任務執行狀態追蹤以及任務結果投遞等相關問題帶來的挑戰。
以上挑戰也是企業在構建分散式業務系統時所面臨的最核心問題,站在產品的角度,我們希望能夠通過非同步任務系統的構建,幫助使用者解決分散式系統中的這些共性的典型問題。客戶只需要關注自己的業務請求提交和執行結果,從請求提交到執行的過程中涉及的Serverless彈效能力,資源排程,系統流控及可靠執行,錯誤重試等細節無需使用者關心,真正實現 Serverless 倡導的幾個核心理念:極致彈性,無伺服器運維、按需付費,最終幫助兌現Serverless對於客戶的業務價值。
在討論了Serverless非同步任務系統構建面臨的多種挑戰之後,通過上面的分析,Serverless非同步任務處理系統功能可以簡單概括為以下四個核心模組:
① 請求託管:負責多租架構的任務託管、使用者請求儲存、獲取使用者請求以及執行使用者請求,如何在多組架構下選擇合適的隔離粒度,更好的實現使用者的請求隔離,如何在使用者隔離需求的基礎上更好的權衡隔離和成本之間的平衡。
② 流量控制:通常使用者選擇非同步任務處理系統,大概率源於請求和消費之間存在矛盾。如何幫助客戶解決使用者請求以及後端資源供給之間的矛盾,更好地執行使用者的任務請求,是非同步系統核心所在,流量控制至關重要。
③ 執行管理:執行管理主要分為兩個層面。首先,如何更好地執行任務,與流量控制更好的聯動,如何用更好的方式排程資源從而更好地執行任務,這也是對系統底層排程的挑戰。其次,如何管理任務請求,比如可能需要在任務執行過程中進行暫停、刪除或批次操作,也需要對執行的任務提供狀態追蹤,瞭解其執行情況,並提供任務去重的能力。
④ 目標投遞:也可以叫結果投遞,需要將任務最終執行結果返回給使用者。關於結果投遞,這裡有多個思考,一種是如何將結果投遞;另一種是如何以更好的方式將結果投遞;對於前者比較直觀,而對於後者,我們希望對於任務執行結果,能夠提供更靈活的再次處理能力,因此在實現上支援將結果投遞到函數計算、MQ,EventBridge等更通用的產品上,使用者可以基於這些產品再次利用事件驅動或相關能力對於任務執行結果進行後續的再次處理,包括傳送簡訊、webhook 等,實現與非同步任務系統進行上下游聯動。
2 Serverless 非同步任務處理系統多租戶架構演進
下圖展示了一個典型的非同步任務處理系統的基本模型,通過 API 的方式進行任務提交、任務排程,任務執行,最後完成執行結果的投遞。
傳統的任務處理框架中,通常會基於服務閘道器進行任務排程、負載均衡和流控策略等能力的建設,這也是分散式系統構建中最基本、但又最核心,最複雜,最需要人力投入重點建設的部分;後端實現通常都是基於程序粒度的記憶體佇列和執行時層面的執行緒池模型完成具體的任務派發和執行。
Serverless 非同步任務處理系統流程為:使用者通過 API 的方式進行任務分發,請求到達Serverless服務閘道器之後,被儲存到非同步請求佇列中,Async Service將開始接管這些請求,然後請求排程獲取後端資源,將這些請求分配給具體的後端資源進行執行。該架構圖中 Async Service負責了傳統架構中請求Dispatcher、負載均衡,流控策略和資源排程的實現,這時候函數叢集相當於抽象的分散式執行緒池模型,在函數計算模型下,範例之間相互隔離,且資源具備水平伸縮的能力,可以避免傳統應用架構下單機資源限制導致的執行緒池容量問題及資源排程瓶頸問題,同時任務的執行環境並不會受整體業務系統執行時的限制,這也是Serverless非同步任務系統相比傳統任務系統的價值所在。
從Serverless任務處理系統的架構來看,其處理邏輯非常簡單,大部分分散式系統依賴的能力全部由Async Service系統角色透明化的進行了實現,對於使用者而言更多的是通過函數化程式設計的方式提供任務處理的實現邏輯,整體架構避免了對基於語言執行時執行緒池的依賴,整個函數計算叢集提供了一個「無限」容量的「執行緒池」,通過服務化的方式,使用者只需提交請求,其他並行處理、流控以及積壓處理全部由 Serverless平臺負責完成。當然在實際的執行過程中,需要結合業務特徵對非同步任務處理的並行度,錯誤重試策略及結果投遞進行一些設定。
接下來,我們將重點講述Serverless非同步任務處理系統構建中的一些技術細節。首先我們從任務分發及請求託管開始講述Serverless非同步任務系統構建過程。
Serverless多租架構下,非同步呼叫請求首先到達系統的 API 閘道器,由API閘道器將接收到的非同步請求放置到非同步佇列中託管;API 閘道器是一個無狀態的架構設計,能夠支援負載均衡和動態擴縮容。
簡單的非同步任務請求託管,在實際的系統實現中,不僅需要考慮租戶之間的請求隔離,也需要考慮相同租戶下不同函數之間的隔離需求;結合客觀的請求隔離需要、請求處理的實時性要求,以及平衡佇列資源的使用成本,我們設計了一套包含多種佇列(Queue)型別,支援動態回收的佇列管理系統,基於這樣的系統實現滿足了多租架構下隔離需求,執行效率,和隔離成本之間的平衡。
這些佇列模型包括賬號粒度的佇列模型,函數粒度的佇列模型以及多賬號共用維度的佇列模型;賬號粒度的佇列作為基本的執行保障,當佇列中某個函數請求執行異常可能對其他函數請求產生影響的時候,會動態地為其分配函數粒度佇列,並將該函數相關的請求路由到專屬佇列中進行處理;同時,對應的函數如果長期沒有請求,在一定時間週期之後,會對之前分配的佇列資源進行動態回收,達到佇列資源的高效利用。
除了定義多種型別的佇列模型之外,面對任務佇列的切換,系統提供了任務請求的動態路由能力,可以自動化地將請求路由到不同型別的佇列中,分發到不同的Partition上快速執行,解決由於Noise Neighbor問題引起的消費積壓或請求負載不均帶來的消費延遲問題。
有同學可能會疑惑,為什麼不一開始給每個函數分配獨立的請求佇列?在雲端計算環境下,佇列本身是一種資源,給每個賬號下的每個函數分配一個Queue資源,看起來是徹底解決了請求的隔離問題,由於函數的量級和佇列系統能夠提供的佇列量級是不對等的,考慮到下游系統的具體實現,結合底層為了滿足實時性的消費處理邏輯,一個函數可能需要分配多個佇列資源,通過並行消費多個佇列滿足請求處理的實施性要求,從實際來看,不僅要考慮Queue的分配效能,還需要考慮Queue資源分配對下游系統的衝擊以及大量Queue資源本身的管理成本;每個函數持有一個Queue的成本也是巨大的,由於不同函數的負載不同,呼叫頻率不同,為其分配獨立的Queue在一定程度上本身就是一種資源浪費,與Queue密切相關的後端消費邏輯也會帶來不必要的大量系統資源消耗,對於Serverless系統而言,這些都是非常巨大的系統資源浪費。
在討論完請求託管的底層設計邏輯之後, 接下來我們將對於非同步請求處理鏈路的流量控制策略做進一步的解釋。
流量控制主要包括兩個部分,一個是面向任務請求消費的動態負載能力,主要是Receiver能力的動態擴容和縮容;另一部分就是後端任務執行排程的反饋能力,通過及時將後端任務處理的結果返回給Receiver ,再通過調整 Receiver 獲取任務請求的速率,最終適配系統後端資源,達到平衡。
具體實現上,系統採用AIMD的反饋控制演演算法,即和性增長,乘性降低。該演演算法在 Serverless的高頻請求或多租架構下,能夠實現更細粒度的控制。整個過程可以將 Receiver和Invoker看作一個Pool,通過結合Pool Size線性增長以及遇到後端消費能力不足負反饋時 Pool Size 乘性衰減,使得 Pool Size 動態收斂到一個匹配後端處理能力的大小,實現系統的流控管理,避免上游請求的不斷獲取對下游資源排程的衝擊,也避免了極端情況下由後端資源排程問題引起的系統飢餓狀態。
Job/Task模式下,業務對於Job和Task請求有追蹤執行狀態的需求,同時客戶對於任務執行有一些高階管理,任務暫停,取消,任務去重等需求,我們在 Serverless非同步任務的基本框架上增加了任務執行狀態機的設計,通過引入狀態機,可以對每個任務進行完整的狀態追蹤,可以基於狀態追蹤對任務執行進行細粒度的控制,也可以基於狀態的控制實現非同步處理的高階操作,比如任務刪除、恢復、去重等高階任務管理功能,狀態追蹤也能夠更好地體現任務生命週期的執行情況。
一個任務處理系統不僅需要幫助客戶完成任務請求和執行,也需要關注任務執行過程中的偵錯或任務執行狀態和各種執行指標的查詢。
Serverless 系統為客戶提供了非常完整的觀測效能力,包括任務請求處理的情況、任務執行的耗時等,同時也提供了任務執行請求列表的查詢,使用者可以通過請求 ID 登入到正在執行的上下文,為使用者提供了接近於傳統操作習慣的過渡;此外,Serverless 系統實現了任務執行過程中生命週期各個階段的耗時展示,為使用者提供了從請求到執行完整的追蹤能力。
3 Serverless 非同步任務處理系統更大的價值
在Serverless非同步任務處理系統中,使用者的請求首先通過閘道器寫入到非同步佇列中,非同步佇列本質是一個MQ, 非同步任務處理系統本質是通過一系列的分散式消費策略,構建一個完整的Producer—Consumer模型,最終完成佇列中每條請求的消費;將這樣的系統模型進一步抽象,除了消費函數計算本身的非同步請求,對於任何的MQ系統而言,都可以構造這樣通用的消費處理層,也就意味著客戶並不需要關注消費本身的系統實現邏輯,只需要提供對於訊息本身的業務處理邏輯;EventBridge和函數計算的深度整合,正是通過這樣系統化方式將訊息消費與訊息處理的邏輯進行分離,正如非同步任務系統所做的那樣,最終實現訊息處理的Serverless化。
按照新的Serverless訊息架構, 使用者無需自己實現消費端的實現邏輯,不需要關注和擔心與消費相關的負載均衡及流量管理等分散式系統問題,針對訊息的業務邏輯以及對下游資料狀態的更改,客戶只需要利用函數計算快速實現自己的業務邏輯,達到快速構建業務系統的目的,這也是Serverless訊息導向場景,能夠給客戶提供的新選擇。
在具體實現上,底層基於EventStreaming模式,消費元件直接從訊息源處拉取訊息,無需中間BUS層轉存直接投遞到目標函數,實現訊息的高效處理;整體架構實現了將有狀態的訊息消費邏輯和無狀態的訊息處理邏輯進行分離。
函數計算系統憑藉其靈活的可延伸性和豐富的連結能力,能夠快速幫助客戶構建自己的業務系統;當然,這也對客戶的業務系統構建提出了諸多的要求,例如需要按照函數程式設計正規化進行程式碼開發,需要遵循函數計算執行模式,整體來看,客戶需要基於Serverless架構對自己的業務系統進行一定的改造適配。
除了微觀上提供的敏捷開發及靈活擴充套件能力之外,我們認為,函數計算系統真正的價值在於其整體的系統原子化能力,能夠在宏觀上作為客戶系統在公有云環境的開箱即用擴充套件,使企業系統架構享受函數計算帶來的資源彈性和靈活擴充套件能力。為了幫助企業利用 Serverless系統原子化的能力實現業務系統的延展,我們在 Serverless 的接入以及 Serverless 執行環境的支援上實現了更簡單的接入方式。
請求提交層面,函數計算提供了HTTP接入方式,客戶只需在自己的系統中整合函數提供的URL 即可將任務提交到公有云環境的函數計算引擎上。同時,函數計算構建了基於EventBridge的通用 PaaS 事件驅動能力,客戶業務系統可以將相關事件投遞到通用的基礎設施上,然後通過EventBridge觸發執行業務邏輯。
在業務系統的 Runtime 支援上, Serverless提供了多種接入方式,比如支援了傳統的自定義映象的執行。客戶映象無需進行任何改造,只需經過簡單設定,即可將自己的任務和相關映象託管在函數計算上,實現業務系統的快速接入,系統的靈活擴充套件和快速延展正是當下雲原生架構所追求的目標。