摘要:本文介紹了華為雲對冷啟動優化這一業界難題的探索之路,創新提出了基於程序級快照的優化方案。
作者資訊——
子游:華為元戎高階工程師
平山:華為雲中介軟體 Serverless 負責人
琪君:華為元戎負責人
Serverless應用啟動時,都需要先進行初始化。其初始化時長一般取決於應用本身的屬性,如業務邏輯、程式語言等,其中Java應用的初始化過程通常是最慢的。以下基於一個典型的Java應用,對其啟動時延進行拆解,各階段耗時分佈如圖1所示:
圖1:Java應用啟動耗時分解
其中,端到端冷啟動耗時可分為2大部分:
主要包含執行環境建立(如容器啟動)、執行環境初始化(如程式碼包下載、部署)等準備工作,此階段最多是秒級響應,在冷啟動整體耗時中佔比很低,通常不到5%,平臺側也支援一些優化方式,將耗時進一步壓縮至毫秒級;
主要包含應用框架啟動(如構建Spring ApplicationContext)、業務初始化(如業務資料初始化)等動作,此階段耗時一般較長。在本例中,應用框架啟動耗時佔比約30%,業務初始化佔比約65%。由此推斷,該階段執行的動作是Java應用啟動慢的核心所在。
Java應用啟動慢的根因其實也不難理解,主要有:
圖2: hello world依賴的class個數
因此,對於時延敏感型的Java應用程式,在突發流量下發生冷啟動時,可能會導致使用者體驗下降。為了應對這一挑戰,使用者可以提前預留資源來減少冷啟動發生的頻率,或者對自己的應用進行效能調優,但是第一類方案無形中增加了使用者的keep-alive成本,第二類方案也有著較高的技術門檻且往往效果比較有限。
業界針對Java應用的啟動速度優化已有一些優秀的實踐,可分為以下幾類:
如Lazy Initialization[3]、Scanning-index[4]等,前者通過懶載入的方式來減少啟動時載入類的數量,一定程度上提升啟動速度;後者通過在編譯階段建立索引,避免啟動時掃描所有路徑來進行加速。但是該類方案在Serverless場景缺乏一定的普適性。
華為雲FunctionGraph創新提出的基於程序級快照的冷啟動加速解決方案,致力於在使用者無感知(無需/少量進行程式碼適配)的前提下,幫助使用者突破冷啟動的效能瓶頸。本優化方案直接從應用初始化後的快照進行執行環境恢復,跳過複雜的框架、業務初始化階段,從而顯著降低Java應用的啟動時延,實測效能提升達90%+。
當用戶Java函數開啟冷啟動加速的設定開關後,華為雲FunctionGraph會預先執行函數對應的初始化程式碼,獲取其初始化執行上下文環境的快照,並進行加密快取。後續呼叫該函數並觸發冷啟動擴容時,會直接從提前初始化後的應用快照來恢復執行環境,而非重新走一遍初始化流程,以此達到極大提升啟動效能的效果。
先結合圖3直觀對比一下優化前、後的冷啟動流程差異:
圖3:基於快照加速的冷啟動流程
基於快照的冷啟動流程,主要包含以下幾個關鍵步驟:
Step 1:平臺側提前準備執行環境,並預執行初始化程式碼、儲存應用快照,此動作後續統稱為Checkpoint
Step 2:在請求到達,觸發函數新範例擴容時,直接從應用快照來恢復新的執行環境,此動作後續統稱為Restore
Step 3:(可選)應用程序從快照恢復後,執行Restore Hook完成業務狀態的重新整理
Step 4:應用Ready,具備接著往下執行業務邏輯的能力
特別的,容器本身也是主機上的程序,故本優化方案也支援容器粒度的Checkpoint,即對容器內指定程序進行CR,與傳統的輕量化虛機快照相比,其精細化程度更高、也更靈活。其原理詳見圖4:
圖4:基於容器的CR流程
華為雲提出的基於程序級快照的冷啟動加速方案,其核心技術依託於CRIU[5],它支援對使用者空間指定的程序進行「凍結」(即停止程序,並將該程序執行的所有上下文持久化為映象檔案),並在必要時對其進行「解凍」(即通過儲存的映象檔案來正確恢復程序執行的上下文),其核心工作流程如圖5-6所示[6]:
圖5:CRIU如何工作——Checkpoint
圖6:CRIU如何工作——Restore
Checkpoint
Restore
如Part II所述,雖然本優化方案能極大提升Java應用的冷啟動速度,但是快照技術在某些場景也存在一定的侷限性,較難做到對現有應用的全透明化。通過快照恢復後,應用的網路連線狀態會受到影響,涉及到TCP Socket重連等場景,如服務註冊、DB連線,分散式通訊,訊息佇列等。
這部分場景依賴應用本身的網路重連機制來更新正確,因此,本優化方案中也引入了Restore Hook的概念,提供手段讓業務對這些狀態進行重新整理。
Restore Hook當前已支援大部分主流第三方元件的重連,詳見圖7:
圖7:Restore Hook支援的第三方元件
不難發現,Restore Hook需要應用本身進行少量的程式碼適配。為了進一步簡化應用的改造負擔,我們也進行了一種新的技術嘗試,可以理解其充當了使用者應用與BaaS之間的紐帶,通過狀態解除安裝等手段,對開發者透明,幫助應用完成狀態的自動化重新整理。這部分探索會在後續的技術博文中跟大家分享,敬請期待。
我們選取了公司內部典型的Java應用,對其原始初始化流程、Restore流程進行了對比測試,如圖8所示。測試結果表明,本優化方案將應用的啟動速度平均提升了95%+,即使快照包的增大一定程度上增加了包下載、解壓的耗時,但最終端到端的冷啟動時延也降低了90%+。
圖8:冷啟加速前後的資料對比
華為雲釋出的基於程序級快照的冷啟動加速方案,是一種效能優化服務,使用者無需額外付費,只需進行簡單的設定、少量的程式碼修改,即可享受到該創新方案帶來的冷啟動效能提升。
下文基於華為雲FunctionGraph,為大家帶來特性Quick Start:
1、登入FunctionGraph控制檯,建立Java函數,並開啟「快照式冷啟動」開關
2、(可選)設定Restore Hook,並在函數程式碼中實現對應的Hook邏輯
3、函數釋出新版本後,觸發快照的自動化製作
4、請耐心等待快照製作完成(5min超時時間)
5、呼叫Java函數,體驗快照優化後的效能提升
本文介紹了華為雲對冷啟動優化這一業界難題的探索之路,創新提出了基於程序級快照的優化方案。當然,本方案也並非十全十美,它依然面臨著一系列挑戰,如文中提到的應用狀態重新整理、程序級CR的精細化控制、多平臺的相容性等,我們也在持續探索、優化中。
同時,FunctionGraph 作為華為元戎核心加持的下一代 Serverless 函數計算與編排服務,致力於持續為使用者提供方便、迅捷的Serverless 服務體驗。您可以登入華為雲FunctionGraph控制檯來深入體驗,更多資訊請參閱FunctionGraph官方檔案[7]。後續我們將分享更多圍繞通用全場景 Serverless的前沿理論及其案例實踐,回饋社群。
[1]https://www.graalvm.org/22.3/reference-manual/java/compiler/
[2]https://wiki.openjdk.org/display/HotSpot/Application+Class+Data+Sharing+-+AppCDS
[3]https://spring.io/blog/2019/03/14/lazy-initialization-in-spring-boot-2-2
[4]https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-scanning-index
[5]https://github.com/checkpoint-restore/criu
[6]https://speakerdeck.com/udzura/introduction-to-criu?slide=32
[7]https://support.huaweicloud.com/functiongraph/index.html