1. 程式人生 > >函數計算性能福利篇(一) —— 系統冷啟動優化

函數計算性能福利篇(一) —— 系統冷啟動優化

重要 51cto 說明 rst 計算 alt 代碼 只需要 生成

摘要: 背景 函數計算是一個事件驅動的全托管 serverless 計算服務。使用函數計算構建應用,用戶只需要專註於實現應用層的邏輯實現;服務器等基礎設施的容錯、伸縮以及運維工作由平臺來完成。因此用戶能在很短的時間內實現彈性高可用的雲原生應用。

背景
函數計算是一個事件驅動的全托管 serverless 計算服務。使用函數計算構建應用,用戶只需要專註於實現應用層的邏輯實現;服務器等基礎設施的容錯、伸縮以及運維工作由平臺來完成。因此用戶能在很短的時間內實現彈性高可用的雲原生應用。

函數計算在容器中執行用戶函數代碼,這樣的環境我們稱為函數實例。實例的生成需要一些額外的系統準備工作,比如選擇執行函數的引擎,下載用戶的代碼,啟動容器,加載函數等等。如果請求的調用鏈路裏包含了上述環節,我們就稱之為冷啟動。實例一旦生成,會持續服務請求;當一段時間內沒有請求後,系統將回收實例。因此,冷啟動通常發生在函數首次調用或者負載升高需要更多的實例來處理對應的請求。

"冷啟動"對於毛刺敏感的業務會顯得不那麽友好,所以冷啟動的優化對於函數計算在延時敏感型場景中的應用尤為重要。

系統架構
在探討調度優化之前,我們先簡要介紹函數計算的架構以及調度方式,如下圖所示。

技術分享圖片

API 服務層完成身份驗證,元數據的讀寫等功能。同步調用函數時,API 服務模塊從資源調度模塊獲取可用的函數執行引擎並發送請求,函數執行引擎根據函數相關信息準備執行所需環境,啟動容器進行計算,最後取回結果。異步調用函數時,則將事件寫入到消息隊列後即返回。由事件分發模塊分發事件,整個流程和同步調用類似。

資源調度模塊主要負責函數計算分布式系統的負載均衡和實時彈性伸縮。當一個用戶請求達到時,資源調度模塊進行第一層調度——分配函數執行引擎,然後在函數執行引擎中進行第二層調度——分配函數實例,進而才開始執行用戶函數。而當用戶一段時間內不再請求,調度系統就會自動回收函數實例和函數執行引擎資源。如下為用戶請求處理資源調度流程:

技術分享圖片

為了保證用戶請求使用的資源,一個函數實例只能同時服務一個請求,所以在用戶請求並發較大的情況下,系統會調度更多的資源來消費該用戶的請求。

如架構圖所示,系統層的"冷啟動"就是從函數執行引擎的獲取到函數實例創建的整個過程,主要的步驟如下:

技術分享圖片

而冷啟動的快慢受限於很多情況,主要因素有用戶代碼大小、網絡因素、runtime 環境因素等,所以,對於實時性要求高的業務場景來說,冷啟動的存在是不友好的。

調優策略
冷啟動問題導致了大量並發到來的時候,毛刺加劇,根源在現存的實例調度方式無法快速響應請求而引起請求在整條鏈路中長時間處於系統新資源的分配等待中。

所以,要提高實例調度速率、快速響應請求,減少排隊請求數,主要著手於如下兩個方面:

加快空閑實例投入使用,提高利用率;
在峰值到來時,加快新實例生成,增加實例儲備。
加快空閑實例投入使用速率這一點,能很大程度上減少請求在鏈路上等待冷啟動的時間,從而加快請求被處理的速率。在用戶函數邏輯執行較快的情況下,實例能夠被快速釋放,如果此時一個正在等待冷啟動的請求能夠探測到已經有實例進入空閑狀態,那麽就會被處理。而之前的冷啟動則轉入後臺繼續進行,生成新的實例,增大實例儲備,應對更多的請求處理。

另外一方面,因為用戶的資源配額在系統層面有限制,比如在超大並發的請求下用戶可能會遇到 ServiceUnavailable 錯誤。而調度策略上如果能夠加快空閑實例投入使用的速率,那麽實際上也減少了冷啟動的次數,即減少了對資源配額的開銷,增加資源利用率,從而減少了被系統流控的可能。

調優結果
根據用戶實際使用場景,我們設計如下兩種測試case來驗證調優效果:

負載持續增加模式
波峰 burst 模式
測試函數的特性如下:

函數自身邏輯運行時間為 100ms;
函數代碼包大小為 50MB;
runtime 為 python2.7;
Memory 為 3GB 。
這樣的函數,如果帶有冷啟動,單次端到端的請求 latency 在 1.7s - 3s,不帶冷啟動的請求端到端 latency 在 105 - 120ms。

負載持續增加模式
該模式下,用戶的請求在一段時間內會持續增長。設計請求行為如下:

每波請求並發數翻倍遞增: 1, 2, 4, 8, 16, 32;
每波請求的時間間隔為 10s。
TPS情況如下,增長率為100%:

技術分享圖片

優化前後對比
10s 聚合的 latency 指標如下監控:
優化前, 平均 latency 在 1000ms 左右,而99%的請求 latency 均在 1.8s 以上。
技術分享圖片

技術分享圖片

優化後,平均 latency 為 200ms 以下(排除第一個完全冷啟動),99% 的請求 latency 大部分在 200ms 左右,較之前下降一個數量級。

技術分享圖片

技術分享圖片

單個請求情況分析
更直觀的分析,我們把每一個請求的端到端 latency列出來比較,如下圖。每一波請求中,都有一半的請求能夠直接使用前一波請求現存下來的實例,而另一半請求都需要等待新的調度。明顯看到,舊的調度策略上,這一半請求幾乎全部都在傻傻等待處於完全冷啟動狀態;新的調度策略中,明顯看到這一半請求都被調度到了提前釋放的實例上被處理,從而大大優化了毛刺情況。

優化前:

技術分享圖片

優化後:

技術分享圖片

波峰 burst 模式
波峰burst模式是指用戶請求比較平穩,但是會有突然的波峰流量場景。設計請求行為如下:

每波請求時間間隔 10s;
每波平穩請求數 2;
burst 請求數 20;
TPS請求如下,burst 流量猛增 10 倍:

技術分享圖片

優化前後對比
10s 聚合的 latency 指標如下監控:
對比99%的請求 latency,毛刺下降了整整一倍多。

優化前
技術分享圖片

優化後

技術分享圖片

單個請求情況分析
按處理順序,我們羅列出優化前和優化後處於 burst 時期 20 個請求的每一個 latency 的情況,如下表。不難發現,除了最前面的兩個請求直接使用了現存的 2 個實例,其他請求全部都是需要等待調度的。優化前,所有的請求都在完全等待冷啟動;而優化後,不難發現,每兩個請求的 latency 處於相同的水平,而前後兩組之間相差 100ms (正好是函數執行時間),從而說明新的調度方式有效的復用了已有的"熱"的容器。
技術分享圖片

實際在線用戶請求優化結果
對在線某一用戶的實時流量跟進分析,看到優化前後明顯對比,如下圖所示。優化前 TPS 在某一時間點從 11 上升到25,此時 99% 的 latency 出現一個明顯的毛刺現象。在2個小時之後,優化開關打開,某一時間點 TPS 達到了 32,此時 latency 無明顯波動。

技術分享圖片

總結
綜上數據分析,在典型的負載變化情況下,冷啟動對 99% 的請求 latency 的影響已經忽略不計,本次調度上的調優大大改善了函數計算在延時敏感場景下的表現。

原文鏈接

本文為雲棲社區原創內容,未經允許不得轉載。

函數計算性能福利篇(一) —— 系統冷啟動優化