3.7.3 函數計算系統設計
在設計函數計算系統時,根據内外部使用者的場景和需求要實作以下目标。
可靠性。系統在面對程序、機器、網絡、可用區等不同程度的故障時,要有 自愈能力。在應用負載快速變化時,系統應當能及時準備好所需計算資源, 保障穩定的服務品質。
多租戶資源共享和隔離。由于使用者按實際使用的資源付費,是以計算資源要被不同使用者的不同應用共享、降低系統成本。系統要具備出色的隔離能力, 避免應用互相幹擾。
安全性。函數計算的定位是通用計算服務,要能執行任意使用者代碼,是以安全是不可逾越的底線。系統應當從權限管理、網絡安全、資料安全、運作時安全等各個次元全面保障應用的安全性。
函數計算采用微服務架構,如圖 3-89 所示,主要由以下幾部分組成。

圖 3-89 函數計算系統架構
賬戶管理服務。負責新賬戶的叢集配置設定,以及從叢集水位管理、使用者隔離角度出發,在不同叢集間遷移賬戶。
前端服務。提供函數計算對外的 API,驗證請求的身份,将請求發送給對應的函數執行個體,收到結果後将其傳回給使用者。
函數執行個體排程服務。函數執行個體是執行函數請求的容器。執行個體排程服務追蹤函數 / 使用者的負載變化,實時伸縮函數執行個體,并在執行個體數超過配額時進行流控。
計算資源。對底層計算資源進行抽象,能夠對接多種資源池,包括容器、虛拟機或者實體機。
計算資源彈性排程
在函數計算中,應用所需的計算資源由平台負責管理。平台要能夠識别應用特征,在負載快速上升時,及時擴容計算資源,保證應用性能穩定 ;在負載下降時, 及時縮容計算資源,加快資源在不同賬戶 / 函數間的流轉,提高資源使用率。是以更
實時、更主動、更智能的彈性伸縮是函數計算系統具備良好使用者體驗的關鍵。函數計算的資源伸縮過程是一個名額收集、線上決策、離線分析、決策優化的閉環。
系統收集多個次元的名額,既有節點次元的資訊,包括 CPU、記憶體、網絡資源 使用率、系統負載等;也有應用次元的資訊,包括請求速率、函數執行個體啟動延時、函數執行延時等。這些名額按照使用者、函數、不同大小的時間視窗等被聚合,最終作為決策依據,被線上伸縮和流控算法使用。
随着平台規模的擴大,記錄和聚合海量函數的資訊在工程實作上面臨較大的挑戰。實踐中,資訊的處理代價和方式應當被仔細考量,以避免影響系統性能。比如, 統計 95 分位請求延時的成本較高,這類資訊一般隻在離線算法中使用,并通過統計算法計算近似的 95 分位資訊,降低計算複雜度。
使用者函數的調用通常是不均勻的,例如 1 秒内發生了 1000 次調用的函數,可能所有的調用請求都是在前 100 毫秒内發生的。如果所有請求都立即被響應,無疑需要在短時間内擴容更多的函數執行個體。待突發請求過後,很多函數執行個體又處于閑置狀态。這樣不但增加了系統壓力,也降低了資源使用率。函數計算系統通過隊列平滑負載毛刺的壓力。函數調用請求首先在隊列中排隊,隻有在有可用的函數執行個體後才被處理。系統按照如下的步驟計算所需的函數執行個體數。
(1)根據函數負載特點确定聚合請求資料的時間視窗,計算請求入隊速率。對于 被密集調用的函數,資料聚合時間視窗不能太大,否則無法識别快速變化的負載,影響性能。對于被稀疏調用的函數,太小的聚合時間視窗可能聚合不到請求,沒有意義。
(2)根據入隊速率、隊列長度、函數執行個體啟動時長、執行個體生命周期、執行個體資源使用率等名額,計算期望的請求出隊速率。
(3)根據出隊速率及函數的執行時間,計算期望的函數執行個體數。
(4)對比已有執行個體數、正在啟動的執行個體數和期望執行個體數,建立或銷毀執行個體。
在建立新執行個體時,系統需要決定如何将函數執行個體放置在下層計算節點上。放置算法應當滿足多方面的要求,如圖 3-90 所示。
圖 3-90 函數執行個體放置算法示例
容錯。當函數有多個執行個體時,将其分布在不同的計算節點 / 可用區上,提高函數的可用性。
資源使用率。在不損失函數性能的前提下,将計算密集型、I/O 密集型等函 數排程到相同的計算節點上,盡可能充分利用節點的計算、存儲和網絡資源, 動态遷移不同節點上的碎片化執行個體,進行“碎片整理”,提高資源使用率。
性能。例如複用曾經啟動過相同函數執行個體的節點,利用緩存的代碼資料,加速函數的啟動時間。
除了線上排程,系統還将天、周或者更大時間範圍的資料用于離線分析。離線分析的目的是利用全量資料驗證線上排程算法的效果、調優參數。通過資料驅動的方式,函數計算的排程大大加快了資源的流轉速度,提高了叢集整體資源的使用率。
負載均衡和流控
函數調用請求到達前端伺服器(Frontend Server)後,首先向資源排程服務申請函數執行個體,再将請求發送給相關的函數執行個體處理。是以資源排程服務是系統的關鍵鍊路。為了支撐每秒近百萬次的資源排程請求,我們将資源排程服務的負載進行分片(Partition),橫向擴充到多台機器上,避免單點瓶頸。分片機制包含兩層資訊的映射:首先将指定函數的資源排程請求映射到對應的分片上;然後将分片排程請求映射到對應的分片伺服器(Partition Server)上。函數執行個體服務負載均衡架構如圖 3-91 所示,前端伺服器首先确定請求所屬的分片,然後通過分片映射表找到對應的分片伺服器(函數執行個體排程節點),再将請求發送給該節點處理。
圖 3-91 函數執行個體服務負載均衡架構
分片管理器(Partition Manager)将負載拆分為 N 個分片,并為每個分片指定對應的分片伺服器,将分片的位置資訊存儲在分片映射表中(Partition Map Table)。分片伺服器通過周期性的心跳向分片管理器彙報分片和節點的負載資訊,分片管理器通過以下三種分片操作實作負載均衡。
分片遷移(Partition Move),将分片遷移到另一台分片伺服器。當分片管理器發現某一台伺服器的負載較高時,可通過分片遷移來平衡負載。
分片分裂(Partition Split),将負載很高的分片分裂為多個分片。通常一個分片上主要的請求來自少數被密集調用的函數。當函數負載增加超過一台分片伺服器的處理能力時,分片管理器将相關分片分裂為多個分片,并指派給不同的分片伺服器處理。
分片合并(Partition Merge),将多個低負載的分片合并為一個分片。
分片管理器監控整個叢集的分片和伺服器負載,通過分片的遷移、分裂、合并三種操作實作叢集處理能力的橫向擴充和負載均衡。叢集不但可以支撐近乎無限的函數,而且單個函數的處理能力沒有上限。
在多租戶環境下,流控是保證服務品質的關鍵。對使用者而言,當函數的調用量超過預期值時,例如函數邏輯錯誤産生大量非預期調用,系統應當及時流控,確定使用者的費用可控。函數計算允許使用者配置最大函數運作執行個體數來限制應用負載。當應用負載上升、系統在擴容時,如果函數執行個體數達到配額上限,那麼将停止擴容并傳回流控錯誤。除了使用者層面的流控,當函數的負載動态變化導緻節點過載時,系統也應當及時流控,避免使用者間互相影響。例如在一個分片上,多個使用者函數負載增加, 導緻分片伺服器過載。此時即使每個使用者都未用滿配額,系統也需要流控。在該場景下的流控,不但要及時,更要做到公平。調用量越大的函數,請求被流控的機率應當越高。
安全性
在函數計算中,應用的安全性由使用者和平台共同負責。函數計算系統管理伺服器 等IT 基礎設施,負責平台的安全,包括硬體、作業系統及編輯語言運作時安全更新檔更新、網絡安全等。使用者負責應用在平台上的安全,包括代碼管理、敏感資料安全通路、身份認證和授權等。
每個函數都在獨立、隔離的環境中被執行。函數計算提供與彈性計算相同的隔離強度。不同使用者不會共享 VM,但同一個 VM 上能運作同一使用者下的不同函數。函數計算會周期性地重置運作時環境,并自動更新作業系統及運作時依賴軟體的安全更新檔。函數計算隔離模型如圖 3-92 所示。
圖 3-92 函數計算隔離模型
在函數計算中,使用者資料包括函數代碼、函數配置、異步調用消息。函數代碼和函數配置加密持久化存儲在對象存儲和表格存儲中。異步調用消息臨時存儲在消息隊列中。對象存儲、表格存儲和消息隊列資源都由函數計算系統管理,使用者不可見。函數計算系統通過 HTTPS 讀寫資料。
通過共享責任的安全模型,函數計算大幅度地降低了應用安全的複雜度。作為一個新興領域,函數計算應用安全處于高速發展的時期。業界在系統可觀察性、運作時 風險注入測試、應用安全分析等領域湧現出大量新興的工具和最佳實踐,幫助使用者以更低的代價實作更好的安全性。