關於雲函數冷啓動優化的思考

關於雲函數冷啓動優化的思考

​ 隨着容器技術的廣泛應用,XaaS形式的概念層出不窮。從IaaS(Infrastructure as a Service)、PaaS(Platform as a Service)、SaaS(Software as a Service)到容器雲引領的CaaS(Containers as a Service),再到火熱的微服務架構,它們都在試着將各種軟、硬件資源等抽象爲一種服務提供給開發者使用,讓他們不再擔心基礎設施、資源需求、中間件等等,在減輕心智負擔的同時更好地專注於業務。FaaS是Functions as a Service的簡稱,它往往和無服務架構(Serverless Architecture)一同被提起。

​ 小程序開發雲函數正是FaaS形式的架構,微信官方對其推崇至極。但是實際的應用情況我們有目共睹,雲函數的冷啓動對客戶端帶來的是高延遲的糟糕體驗。一個雲函數冷啓動,需要經過資源調度,代碼下載,代碼部署幾個步驟。還沒等到執行代碼邏輯,用戶已經退出程序了。如果僅僅從雲函數現在的表現出發進行分析,想要去撼動現在市場格局是遠遠不夠的。

​ 本人技術水平有限,也不知道雲開發的完整的技術框架,只從可能的幾個角度進行分析,找尋可能存在的優化方向,如果錯誤,希望各位不吝斧正。

# 思路一

​ 在雲函數中調用另一個雲函數邏輯,假設執行 \(A\) 雲函數邏輯需要 \(T_1\) 時長,冷啓動需要 \(C_1\) 時長,執行 \(B\) 雲函數邏輯需要 \(T_2\) 時長,冷啓動需要 \(C_2\) 時長。

那麼執行這個邏輯的需要總時長大概是 \(T_1 + C_1 + T_2 + C_2\)

​ 那麼是否可以對上傳的雲函數代碼進行上下文分析,如果雲函數中存在對其他雲函數(如 \(B\) 雲函數)的調用,在冷啓動 \(A\) 雲函數時,也調度資源給 \(B\) 雲函數。

思路簡述如下:

  1. 對上傳代碼分析,將上下文出現的對其他雲函數的調用記錄下來,記作 link_container_list
  2. 在調用雲函數之前,檢查該雲函數的 link_container_list,冷啓動該雲函數同時,對link_container_list中的雲函數也進行冷啓動(資源調度)。

那麼執行這個邏輯的需要的總時長大概是 \(T_1 + T_2 + max\{C_1,C_2\}\)

該思路可以進行拓展,即使有\(N\) 個相關的雲函數,那麼理想情況下最終執行的邏輯時長,也是 \(\sum_{i=1}^{n}T_i + max\{C_1,...,C_n\}\)

# 思路二

​ 雲函數創建對應資源容器時,裝載的資源包括號稱比黑洞更重的node_modules依賴文件等。這或許是影響冷啓動速度的原因之一。

那麼服務提供商是否可以維護這樣一個容器池,容器池中存放着已經裝載完依賴環境的半完成態容器。

如何維持半完成態的容器?

​ 用戶第一次調用雲函數時,以nodejs雲函數爲例,判斷package.json文件中的依賴,容器池中是否有滿足的半完成態容器,將對應容器直接分配該用戶,半完成態容器直接裝載業務邏輯代碼,跳過裝載依賴文件和環境這一步。

# 思路三

​ 考慮業務上的相關聯,比如說對於購物小程序來說,當用戶調用查詢商品詳情雲函數 \(A\) 時,那麼下一步用戶可能就要調用 統一下單雲函數\(B\) 。顯然,在調用 \(A\) 雲函數時,對 \(B\) 雲函數進行資源容器預裝載是合理的,一般習慣稱這種方法叫預熱。 這是業務邏輯上的關聯,然而不同的程序有不同的關聯邏輯,服務提供商是否可以提供一個配置文件,由開發者指定預熱的雲函數資源容器。

​ 例如對於查詢商品詳情的雲函數\(A\) , 假定其關聯預熱雲函數文件名爲trigger.json

{
	"uniOrder",//統一下單
	"addCart",//加入購物車
	"addFavor"//加入手冊
}

​ 當調用雲函數 \(A\) 時,就會預熱 uniOrder等雲函數。

​ 現在對於這種預熱方法的實現方式,是在調用雲函數 \(A\) 的時候,在執行代碼邏輯內部 cloud.callFunction() 來提前預熱雲函數,這種寫法方式不夠優雅,而且如果對正常觸發和預熱觸發邏輯處理不夠完善,還可能會引起其他問題。

# 思路四

​ 既然冷啓動的原因是因爲資源容器會被銷燬,再次觸發需要重新創建,那麼爲什麼不能一次創建長期維持呢?保持最小的資源消耗的情況下,使得雲函數容器不被銷燬,相比較於每次冷啓動對用戶端明顯的交互影響,這些微不足道的資源消耗簡直不值一提。服務商可以給願意付出資源消耗量的開發者提供配置,由開發者指定每次創建容器的存活時間。

​ 例如在config.json文件中新增配置項keep_alive:60,就代表容器如果60分鐘內無操作纔會被銷燬。配置爲 0 代表永不銷燬,然後爲開發者提供個主動銷燬容器的方法調用。

​ 現階段,開發者們常用維護容器狀態的思路是配置定期器,每隔一段時間觸發一次,以維持容器不被銷燬,這樣子對資源的消耗量其實是比較大的。而且是不夠優雅,屬於空邏輯,還需要爲觸發器實現專門的空邏輯處理部分,防止對業務代碼產生干擾。

# 思路五

​ 既然客戶端開發可以使用插件,可以依賴於第三方服務,那麼爲什麼雲函數不可以呢?雲服務商可以提供常駐的通用的雲函數服務,如提供一個用戶角色權限管理雲函數,不需要用戶自己設計部署,由官方提供調用方式即可。

亦或者是提供一個地址管理雲函數,與官方數據打通,使用雲函數提供調用方法等等,不勝枚舉。

​ 總而言之,言而總之,我是很喜歡FaaS架構的開發形式,如果能解決冷啓動對交互體驗的影響,我相信會有更多的開發者投身於這個生態中。

參考文獻

[1] 苗立堯. Faas,又一個未來? [EB/OL] 求知

[2] Linux中國. 如何提升你的雲函數性能 [EB/OL] 小程序官方社區

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章