作者簡介
邢奇(薯片)
螞蟻集團技術專家,雲原生和 Service Mesh 領域專家
長期從事服務治理和服務發現等相關領域的研究和實踐,在 RPC 框架(Dubbo、Spring Cloud 和 SOFARPC 等)方面有源碼級的研究和貢獻;在 Service Mesh、雲原生、容器和 K8s 等方面有深入的研究和實踐經驗。
參與了多個開源項目的貢獻,包括 MOSN、SOFA、Dubbo 和 Nacos 等。目前擔任螞蟻雲開發技術負責人,負責支付寶雲開發產品的研發和實踐。
本文 5689 字,預計閲讀 16 分鐘
概述
什麼是 FaaS ?
在 ChatGPT 裏面輸入 FaaS 關鍵字,得到的結果是:FaaS 是一種雲計算服務模型。它允許開發者編寫和部署函數,而不需要管理底層基礎設施的運行,即 Function as a Service。
同時通過 ChatGPT 可以生成對應的函數代碼——
FaaS 的崛起
FaaS 的理念和函數研發模式,為傳統的應用模式解決了許多問題,有着超前的優勢。
傳統應用模式的困境
在研發態,不管是單體應用還是微服務應用,亦或是 Mesh 架構或者應用運行時,在研發態,開發者除了要關注業務邏輯本身之外,經常會被中間件所打擾,需要配合去做 SDK 升級改造,性能或者功能優化等。同時在使用雲產品或者雲服務的時候,需要被迫去感知多雲的差異。
在運維態,開發者面臨着更重的運維壓力。當一個應用上線,開發者需要對這個業務的未來發展進行一個複雜且不確定的容量評估,再去為這個容量去申請對應的資源,最後經過一個複雜的上線流程進行發佈。在發佈結束之後,開發者還得時刻關注線上流量的變化,去進行不斷的擴容和縮容的調整。
總而言之,整個中間件和基礎設施對開發者的打擾是非常嚴重的:
- 應用研發模式的代碼耦合嚴重,複雜度高;
- 運維流程繁瑣,效率低;
- 容量評估一般很難符合真實情況,線上的資源利用率一般都較低,存在着浪費。
於是 FaaS 函數的研發模式應運而生。
可以很直觀地看到,在傳統應用和微服務應用的改造和優化的基礎之上,FaaS 希望做得更進一步,更面向未來。以函數為編程對象,用户無需關注應用、機器等數據和基礎設施信息。
通過這樣的改變,大大提升研發效能,做到快速開發;並且提高運維效率,提供一站式免運維的 Serverless 平台;最後,函數會隨着流量進行創建和銷燬,最終降低成本和資源的消耗。
FaaS 使用場景
儘管 FaaS 具有許多優勢,但並非所有場景都適合採用函數編程模式。下面介紹一些 FaaS 適用的普遍場景:
1、BFF 的場景。 即一些膠水代碼(對接多個接口、進行數據的組裝和適配等)。膠水代碼的邏輯相對簡單,但同時需求變化快、生命週期短。對應的應用場景如運營/營銷活動等。活動結束之後,就不再有流量進入,也沒有必要再進行代碼和機器的維護。
2、事件驅動的場景。 例如音視頻轉碼,用户上傳文件觸發任務,或者通過消息觸發調度,或者業務上有明顯的波峯和波峯的流量特徵。
3、中台型業務。 例如算法平台的算子。算子計算是非常獨立的業務邏輯,但是參與的研發人數非常多,邏輯相對來説不可控,需要有更高的隔離能力。
FaaS 落地面臨的技術問題
FaaS 技術產品的落地,可能會面臨以下問題和挑戰:
性能問題:
1、在傳統的微服務架構下,開發者會為 RPC 調用性能進行了大量的優化;在 FaaS 的場景,也需要保證函數調用的性能。
2、彈性擴縮容的反應時效性。很多 FaaS 產品會採用彈性的模型去採集 CPU、QPS 併發等指標,再通過平台去計算指標,進而進行一些擴容和縮容的操作,時效性很低。
3、函數啓動的速度。函數啓動的速度在 FaaS 場景中至關重要,函數容器的創建和啓動不僅僅是發佈態的事情,而是一個數據面流量的依賴。
安全問題:
1、想要充分地利用計算資源以降低成本,其必要的前提就是有效地利用和隔離資源。
2、代碼容器。用户的函數代碼跑在容器裏面,防止容器逃逸就是重中之重。
3、相較傳統的編程模型而言,FaaS 的編程模型到底是如何屏蔽中間件以及雲服務的干擾的呢?
螞蟻 FaaS 技術架構
螞蟻在 FaaS 實踐之初設定了 3 個 FaaS 技術架構實踐的基本原則。
原則 1:流量模型。 螞蟻的函數容器是隨着流量進行創建和銷燬的,而不是通過指標數據進行分析的彈性模型。
原則 2:函數冷啓動。 儘管有 Warm Pool 或者 cache 技術可作選擇,但為了最大程度降低成本和利用資源,螞蟻將目標定為 100ms 以內的極致的冷啓動。
原則 3:安全隔離。 用户的函數都跑在我們的容器裏面,因此必須保證高水位的安全隔離特性。
其實,螞蟻在實踐 FaaS 技術架構時,有一個總的原則就是 one request per instance—極致的情況下,是創建一個函數容器去處理一個請求,類似編程模型創建一個線程去處理一個請求。在這裏,創建函數容器就相當於創建一個線程,具有相似的快速、消耗低的優點,同時還有線程所不具備的安全隔離特性。
架構説明
組件介紹和功能説明
函數網關:負責對函數請求進行轉發和控制,併為每一個請求發起一次容器調度任務。
容器調度引擎:負責對容器進行調度,維護容器的整個生命週期,並且可以對函數容器進行併發度和複用等狀態控制,同時也負責管理整個集羣的函數 Pod 資源池。(函數 Pod 資源池是函數容器運行的一個環境,一個集羣內會有 N 多個 Pod 資源池。 )
函數運行時:函數運行時是 OCI 標準的實現,它負責快速地啓動函數容器,並對容器的 runtime 進行有效的控制。
函數容器:函數容器可以理解為是函數運行時+runtime+用户代碼的一個運行態,用户的函數代碼就跑在函數容器中。
數據面流量和調度流程説明
從上圖可以看到,所有請求都會通過函數網關進入到函數集羣,函數網關會發起一次調度任務:通過容器調度引擎 Scheduler 為這一請求快速分配一個 Pod 資源。然後網關就會把這個流量轉發給這個 Pod 資源裏面的節點網關,節點網關隨即緩存對應的請求,並且等待函數容器啓動。同時函數節點調度器會併發地創建函數容器並且為容器掛載函數代碼。函數容器在啓動完成之後,就會立刻作為一個客户端去節點網關上拉取請求,然後進行業務邏輯處理。
從上述流程中可以看到,螞蟻 FaaS 場景中的 Serverless 有了第二層含義——no server(沒有 server)。函數容器永遠是作為一個 client 去處理請求。這樣的方式從設計上就避免了對基礎設施環境的依賴,同時減少了需要去打開一些網絡端口、處理網絡連接的損耗,也不需要像微服務應用那樣去做一些 checkhealth 和 readliness 探針等之後才能進行註冊,然後再進行服務發現和調用。
性能優化實踐
函數網關
FaaS 函數網關採用 Go 語言進行編寫,網絡編程模型是通過一個 go routine 處理一個請求的同步編程,比較符合開發者的習慣。同時由於 Go 語言良好的垃圾回收機制和 GPM 調度模型,網關也有了不錯的性能。但是隨着業務的不斷增長,整個網關在高併發下會出現毛刺現象,P99 長尾也比較嚴重。
基於以上情況,新版的 FaaS 函數採用 Go 語言的 Gateway 運行在 C++ 語言的 Envoy 運行時上。我們知道,越靠近 Linux 原生語言的方式性能越好。同時 Envoy 採用高性能的同步非阻塞網絡編程模型,性能更優。所有的函數請求通過 Envoy 的網絡接口進入,並且進行網絡處理,然後通過 cgo 調用 Go 語言網關實現的 API 接口,這樣 Gateway 網關就能在七層去做一些 filter 和路由的邏輯。最後將請求轉發給對應的節點網關。節點網關會進行請求的緩存,同時可以收斂網關連接數。同時函數容器在 running 之後會通過 UDS 和節點網關進行交互。
通過上述優化,可以看到整個函數網關的吞吐上升,並且在同樣吞吐的情況下,網關的 CPU 能夠下降 50% 以上,而請求耗時下降 30% 左右。
容器調度引擎
HUSE 容器調度引擎,作為螞蟻容器調度引擎的下一代架構,是專門面向高吞吐、低延遲、低成本、急速啓動的 Serverleess 場景而設計的。目前應用在 FaaS 場景,以及一些 batch job、ODPS、大數據等場景。
為了能夠實現高吞吐、低延遲等功能,HUSE 提供瞭如:多級自適應緩存、高速的協議通訊棧、智能包加載等性能優化,同時也支持高可用和自運維功能。
在性能上,可以看到 HUSE 容器調度引擎的性能數據,在全集羣 1 萬 QPS 吞吐壓力下,整個 HUSE 的調度耗時 P50 基本上在 21ms 左右,P99 在 50ms 以內。相比於傳統的容器調度引擎,有着數量級級別的提升。
全集羣 10000 QPS 調度吞吐下,HUSE 可以實現平均 21ms 的容器調度延遲
100ms 函數容器冷啓動
最後也最重要的一部分,函數容器冷啓動性能優化實踐。雖然在服務端也做了一些優化,但是服務端整理的耗時本身也不過幾毫秒,可優化空間很小。因此整個函數請求耗時的大頭還是在函數容器的冷啓動上。而關於函數容器冷啓動,有四個方面可以進行性能優化。
第一,是從 Warm P ool 模式變成完全的冷啓動。在併發的場景下,cache 技術本身也會佔用 CPU 核數和計算資源,並不會有太多的性能提升。
第二,容器資源實時分配改為緩存資源。容器運行依賴一些資源,比如 IP,下載鏡像,掛載 volume,設置 cgroup 和 namespace 等。這些資源分配都很慢,基本是分鐘級別。而螞蟻 FaaS 對容器所依賴的所有資源,只要不佔用 CPU 和 Mem 的話,都會對其進行緩存,最終將資源分配的速度做到 0ms。
第三,傳統的文件系統,創建、掛載以及訪問都比較慢,螞蟻 FaaS 採用 ROFS 的文件格式,即 Read Only File System 的方式去進行優化。
第四,是容器的啓動方式。標準的 OCI 容器的啓動方式是 create+ start,啓動速度很慢,而螞蟻 FaaS 採用了 checkpoint+restore 技術進行性能優化。
螞蟻函數運行時介紹
容器運行時分為 runC、runD 和 runSC 等不同類型。runC 的安全隔離太差,runD 的啓動速度太慢並且資源消耗太高,都不適合 FaaS 的場景。NanoVisor 是螞蟻 runSC 安全容器。它是 Go 語言編寫的安全容器,重構於開源的 gVisor 項目,是為雲原生設計優化的、彈性安全容器。它也是輕量級 HyperVisor,進行 syscall interception 和 host syscall 加速。支持多個平台的運行,同時在性能方面尤為出色,可以支持一些火焰圖性能分析,並且對 Go Runtime 進行優化,同時引入了高性能的用户態協議棧。目前應用在 FaaS 和一些增強安全的場景。
ROFS 文件系統優化
上圖中可以看到,一個容器會有兩個進程, runSC Sandbox 進程和 Gofer 進程,容器鏡像解壓成 Rootfs 文件 bindmount 到 Gofer 進程中,用户函數代碼也一樣。Sandbox 需要訪問函數和系統文件,需要經過 syscall 然後被 Gofer 進程攔截和控制。這種方式是為了保證安全,但是多了一個進程佔用 CPU 核數,同時函數訪問系統文件都需要進行 syscall ,拉低了速度。
ROFS 文件系統優化,就是將鏡像和用户代碼都編譯成 ROFS 可以解析的格式,並且在沙箱外部打開。同時通過 mmap() 映射到沙箱進程中去。通過這樣的方式,可以降低一半的 CPU 佔用,同時所有文件的操作都變成了內存操作。不僅更加快速,而且更加安全。
容器啓動方式優化
一個標準的 OCI 容器會提供兩個相關的接口:create 和 start。create 是根據容器鏡像和配置文件創建容器運行的環境,對應 NanoVisor 容器沙箱的創建和應用程序內核的初始化;start 則是啓動容器,對應 NanoVisor 容器沙箱內一號進程(Nodejs Runtime)的創建和啓動。這個過程非常慢。
螞蟻 FaaS 採用的是 checkpoint + restore 方式進行容器的恢復。首先按照傳統方式創建、啓動一個容器,等待容器內的 Nodejs Runtime 初始化完成之後,使用 checkpoint 技術對 Nodejs Runtime 進程和應用程序內核 sentry 進行狀態、數據的保存。可以理解為對整個容器進行了一個內存快照,然後導出 checkpoint.img 的種子文件。這樣的話,下一次有請求過來,直接從 checkpoint.img 種子恢復函數容器,也就是 restore 的過程。所以 restore 就是直接利用之前保存好的進程、內核狀態和數據進行恢復,不再需要重新初始化 Nodejs Runtime。在恢復完成之後,Nodejs Runtime 就可以立刻進行業務邏輯處理。
通過以上的優化,目前 FaaS 函數容器落地的啓動速度達到了 90ms 以內,額外的內存開銷要小於一兆,這一提升相當可觀。其中使用到的 NanoVisor 作為螞蟻的第三代安全容器,始於安全。因此之後可以期待在性能提高和成本縮減上能夠做到十倍甚至百倍的一個提升。
目前業界的類似產品中,AWS Lambda 函數的冷啓動性能是比較好的:在 Node.js 運行時環境,平均冷啓動時間為 200ms。
需要注意的是,此數據僅供參考,實際情況會受多種因素影響。
安全能力建設
性能優化的同時,安全功能也必須得到保障。以螞蟻 FaaS 安全功能的建設為參考。函數容器(runSC Sandbox)是一個完全隔離的 runSC 沙箱環境,配置有 ACL 規則和虛擬的 veth pair 網卡。這個網卡是完全虛擬的,沒有任何意義,而且在 FaaS 的場景下基礎設施從設計上本身就是透明的。網卡的另一端插在 bridge 網橋設備上,並且通過 eBPF 進行高效的網絡過濾、控制和轉發。因此整個函數容器沙箱是完全隔離的。
縱向容器防逃逸
函數程序運行在虛擬化的 guest 態,它的系統調用會被 sentry(運行在 Guest Kernel 態和 Host Kernel 態) 也就是 NanoVisor 處理和響應。NanoVisor 運行在 Guest Kernel 態和 Host Kernel 態, 處理所有函數實例的系統調用,進行限制和管控。同時 NanoVisor sentry 本身的系統調用也會由 seccomp 進行限制。
FaaS 的場景基本隔離掉了基礎設施信息,因此限制的接口會更多,攻擊面會更小更安全。同時 NanoVisor 提供進程級別的 NanoVM 虛擬化技術,是一個輕量級的 VMM 管理,作為 host 上的一個內核模塊,可以有效保障內核安全。
橫向安全能力
在橫向控制上,NanoVisor 也做了很多能力建設,包括對所有的網絡操作,包括 accept 一些端口、監聽 DNS 請求等,都會進行網絡審計。同時基於四層網絡的五元組信息,都可以進行 ACL 控制。
免鑑權調用
隔離之外,互通也值得關注。所有函數都通過函數網關進入,但是用户函數代碼也需要訪問其他的服務。一些場景比如函數代碼裏面可以訪問其他的函數、訪問雲服務、訪問 DB 和 OSS 等,或者訪問公網,或者訪問多雲的 VPC 或者 IVS 的 VPC。
在這樣的情況下,螞蟻 FaaS 建設了對應的代理服務和網絡設備,在四層為這些服務打開 ACL 控制,同時會在七層進行應用層的認證和授權。認證和授權的過程完全由 runtime 和代理服務實現,整個過程對開發者是完全透明和無感的。所以開發者也不需要設置 IP、賬號/密碼等信息,這樣可以最大限制地屏蔽中間件、基礎設施和多雲的干擾。
體驗
有着這樣的整體架構,再加上性能的優化實踐和安全能力建設,螞蟻 FaaS 的產品使用體驗是什麼樣的呢?
研發態的體驗: 從創建函數到編寫函數到執行函數,基本上幾秒鐘就能夠完成一個函數代碼的上線。和傳統應用模式對比鮮明,不需要去申請應用創建代碼倉庫,編寫代碼,編譯打包等。曾經在 7 月的一次活動中,一個六年級的小朋友現場花 5 分鐘,就完成了整個支付寶小程序+FaaS 雲函數的開發。
運維體驗: 由於整個螞蟻 FaaS 的設計都是符合 Serverless 理念,所以這裏看不到任何基礎設施信息,但是可觀測性相關的鏈路日誌指標告警是完全具備的。作為 Serverless 的一站式免運維的平台,它能夠自動集成監控和告警功能。
總結
總之,螞蟻 FaaS 的改變和優勢在於:
- 從成本上來説,更小內存開銷、更快啓動速度。用户只用為流量付費,甚至只用為其函數代碼的運行時間付費。(而運行時間可壓縮至一個毫秒。)
- 更高保的安全隔離,能夠進行免鑑權的調用。更快的研發速度、更高效的運維。
- 可以快速開發,沒有複雜的流程,也沒有碎片化的代碼版本的困擾。
- 完全 Serverless 一站式免運維平台,能夠集成監控和告警。
展望:FaaS + AI 開啓編程新紀元
螞蟻 FaaS 對未來的展望包括對極致性能與極致效能的追求,將通過 fork 等技術去實現更高的性能,同時通過 AIGC 等智能化方式去達到極致研發效能。
極致性能
在極致性能的實現中,螞蟻目前正在調研的 fork 技術,函數冷啓動時間已經達到了 3.5ms,穩定地跑進 10ms 以內。有着這樣的啓動速度,函數容器的創建跟創建一個線程一樣又快、開銷又低。同時 fork 技術還可以進行和 runtime、和 user code 的組合,讓啓動再加速。
極致效能
追求極致效能的方式,就是 FaaS+AI。在文章最開始,可以看到 ChatGPT 生成的一段函數代碼,只要十幾行代碼就可以完成一個業務邏輯的處理。所以 AIGC+FaaS 並非紙上談兵,而是很有前景的,並且將會在不遠的未來落地實踐。AI+函數開發模式會結合一些低代碼平台,並且利用螞蟻集團的 NLP GPT/ Code GPT/ OpsGPT 等智能化平台,去演進和誕生一些新的產品形態和編程體驗。想象未來 PD 或運營通過自然語言,和 AI 平台溝通,由 AI 平台生成一些格式化的 PRD,再輸入到類似低代碼/無代碼的平台,平台一方面集成 AI 的代碼生成能力,一方面集成 FaaS 的 Serverless 功能,這樣將大大提高研發效能。
在過去的幾年裏,雲原生技術已經改變了整個運維體驗。但是直到今天,研發模式持續了二十多年,還是一成不變,開發者們還是在電腦面前苦哈哈地敲着鍵盤。希望未來 FaaS+AI 能開啓編程新紀元,顛覆整個研發體驗。
FaaS 延伸支付寶雲開發
FaaS 技術體系在螞蟻已經十分成熟,今年基於螞蟻 FaaS 技術體系沉澱,打造了一款支付寶小程序雲開發產品,歡迎大家瞭解試用。
歡迎大家搜索釘釘羣號:25600034150,加入支付寶雲開發釘釘支持羣瞭解試用:
產品官網:https://cloud.alipay.com/main/product/cloudbase
推薦閲讀
1、如何看待 Dapr、Layotto 這種多運行時架構?
2、Service Mesh 的下一站是 Sidecarless 嗎?
3、MoE 系列(七)| Envoy Go 擴展之沙箱安全
4、Seata-DTX|分佈式事務金融場景案例介紹