當 Knative 遇見 WebAssembly
簡介: Knative 可以支援各種容器化的執行時環境,我們今天來探索一下利用 WebAssembly 技術作為一個新的 Serverless 執行時。
作者:易立
Knative 是在 Kubernetes 基礎之上的 Serverless 計算的技術框架,可以極大簡化 Kubernetes 應用的開發與運維體驗。在 2022 年 3 月成為 CNCF 孵化專案。Knative 由兩個主要部分組成:一個是支援 HTTP 線上應用的 Knative Serving,一個是支援 CloudEvents 和事件驅動應用的 Knative Eventing。
Knative 可以支援各種容器化的執行時環境,我們今天來探索一下利用 WebAssembly 技術作為一個新的 Serverless 執行時。
從 WASM、WASI 到 WAGI
WebAssembly(簡稱 WASM)是一個新興的 W3C 規範。它是一個虛擬指令集體系架構(virtual ISA),其初始目標是為 C/C++等語言編寫的程式,可以安全和高效地執行在瀏覽器中。在 2019 年 12 月,W3C 正式宣佈 WebAssembly 的核心規範成為Web標準, 大大推進了 WASM 技術普及。今天,WebAssembly 已經得到了 Google Chrome、Microsoft Edge、Apple Safari、Mozilla Firefox 等流瀏覽器的全面支援。而更加重要的是,WebAssembly 作為一個安全的、可移植、高效率的虛擬機器沙箱,可以在任何地方、任何作業系統,任何 CPU 體系架構中安全地執行應用。
Mozilla 在 2019 年提出了 WebAssembly System Interface(WASI),它提供類似 POSIX 這樣的標準 API 來標準化 WebAssembly 應用與檔案系統,記憶體管理等系統資源的互動。WASI 的出現大大拓展了 WASM 的應用場景,可以讓其作為一個虛擬機器執行各種型別的服務端應用。為了進一步推動 WebAssembly 生態發展,Mozilla、Fastly、英特爾和紅帽公司攜手成立了位元組碼聯盟(Bytecode Alliance),共同領導 WASI 標準、WebAssembly 執行時、工具等工作。後續微軟,谷歌、ARM 等公司也成為其成員。
WebAssembly 技術仍然在持續快速演進中,2022 年 4 月,W3C 公佈了 WebAssembly 2.0 的第一批公共工作草案,這也成為其成熟與發展的重要標誌。
WASM/WASI 作為一種新興的後端技術,具備的的原生安全、可移植、高效能,輕量化的特點,非常適於作為分散式應用執行環境。與容器是一個一個獨立隔離的作業系統程序不同,WASM 應用可以在一個程序內部實現安全隔離,支援毫秒級冷啟動時間和極低的資源消耗。如下圖所示:
圖片來源:cloudflare
目前 WASM/WASI 還在發展初期,還有很多技術限制,比如不支援執行緒,無法支援低階 Socket 網路應用等等,這極大限制了 WASM 在伺服器端的應用場景。社群都在探索一個能夠充分適配 WASM 的應用開發模型,揚長避短。微軟 Deislabs 的工程師從 HTTP 伺服器發展的歷史中汲取靈感,提出了 WAGI - WebAssembly Gateway Interface 專案[1]。沒錯 WAGI 的概念就是來自於網際網路的上古傳奇,CGI。
CGI 是“公共閘道器介面”(Common Gateway Interface)的簡稱,是 HTTP 伺服器與其它程式進行互動的一種規範。HTTP Server 通過標準輸入、輸出介面等與 CGI 指令碼語言進行通訊,開發者可以使用 Python/PHP/Perl 等各種實現來處理 HTTP 請求。
一個非常自然的推演,如果我們可以通過 CGI 規範來呼叫 WASI 應用,開發者就可以非常輕鬆地利用 WebAssembly 來編寫 Web API 或者微服務應用了,而且無需在 WASM 中處理太多的網路實現細節。下圖就是 CGI 與 WAGI 的概念架構圖對比:
二者架構上高度相似,其不同之處是:傳統 CGI 架構,每次 HTTP 請求會建立一個 OS 程序來進行處理,由作業系統的程序機制來實現安全隔離;而 WAGI 中 ,每次 HTTP 請求會在一個獨立的執行緒來中呼叫 WASI 應用,應用之間利用 WebAssembly 虛擬機器實現安全隔離。在理論上,WAGI 可以有比 CGI 更低的資源損耗和更快的響應時間。
本文不會對 WAGI 自身架構以及 WAGI 應用開發進行分析。有興趣的小夥伴可以自行閱讀專案文件。
進一步思考,如果我們可以將 WAGI 作為一個 Knative Serving 執行時,我們就可以建立起一座將 WebAssembly 應用於 Serverless 場景的橋樑。
WAGI 應用冷啟動分析與優化
冷啟動效能是 Serverless 場景的關鍵指標。為了更好了瞭解 WAGI 執行效率,我們可以利用 ab 做一個簡單的壓測:
$ ab -k -n 10000 -c 100 http://127.0.0.1:3000/
...
Server Software:
Server Hostname: 127.0.0.1
Server Port: 3000
Document Path: /
Document Length: 12 bytes
Concurrency Level: 100
Time taken for tests: 7.632 seconds
Complete requests: 10000
Failed requests: 0
Keep-Alive requests: 10000
Total transferred: 1510000 bytes
HTML transferred: 120000 bytes
Requests per second: 1310.31 [#/sec] (mean)
Time per request: 76.318 [ms] (mean)
Time per request: 0.763 [ms] (mean, across all concurrent requests)
Transfer rate: 193.22 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.6 0 9
Processing: 8 76 29.6 74 214
Waiting: 1 76 29.6 74 214
Total: 8 76 29.5 74 214
Percentage of the requests served within a certain time (ms)
50% 74
66% 88
75% 95
80% 100
90% 115
95% 125
98% 139
99% 150
100% 214 (longest request)
我們可以看到 P90 請求響應時間在 115ms,就這?這個和我們對 WASM 應用輕量化的認知不同。利用火焰圖,我們可以快速定位到問題所在:prepare_wasm_instance 函式消耗了整體應用執行 80% 的時間。
經過對程式碼的分析,我們發現在每次響應 HTTP 請求過程中,WAGI 都要對已經編譯過的 WSM 應用,重新連線 WASI 以及 wasi-http 等擴充套件和並進行環境配置。這消耗了大量的時間。定位了問題,解決思路就非常簡單了,重構執行邏輯,讓這些準備工作只在初始化過程中執行一次,無需在每次 HTTP 請求過程中重複執行。具體可參考優化過的實現[2]
我們重新執行一遍壓力測試:
$ ab -k -n 10000 -c 100 http://127.0.0.1:3000/
...
Server Software:
Server Hostname: 127.0.0.1
Server Port: 3000
Document Path: /
Document Length: 12 bytes
Concurrency Level: 100
Time taken for tests: 1.328 seconds
Complete requests: 10000
Failed requests: 0
Keep-Alive requests: 10000
Total transferred: 1510000 bytes
HTML transferred: 120000 bytes
Requests per second: 7532.13 [#/sec] (mean)
Time per request: 13.276 [ms] (mean)
Time per request: 0.133 [ms] (mean, across all concurrent requests)
Transfer rate: 1110.70 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.6 0 9
Processing: 1 13 5.7 13 37
Waiting: 1 13 5.7 13 37
Total: 1 13 5.6 13 37
Percentage of the requests served within a certain time (ms)
50% 13
66% 15
75% 17
80% 18
90% 21
95% 23
98% 25
99% 27
100% 37 (longest request)
在經過優化過的實現中,P90響應時間已經下降到 21ms,其中 prepare_wasm_instance 所佔執行時間已經下降到 17%。整體冷啟動效率有了很大的提升!
注:本文利用 flamegraph[3] 進行的效能分析。
利用 Knative 執行 WAGI 應用
為了讓 WAGI 可以作為 Knative 應用執行,我們還需在 WAGI 上增加了對 SIGTERM 訊號的支援,讓 WAGI 容器支援優雅下線。具體細節不再贅述。
Knative 的環境準備可以參考 Knative 安裝文件[4],利用 Minikube 建立本地測試環境。
注:前提是需要有一定的網路能力,因國內無法訪問在 gcr.io 中的 Knative 映象。
一個更加簡單的方式是直接使用阿里雲 Serverless 容器服務 ASK[5] 上 Serverless K8s 叢集。ASK 內建了 Knative 支援[6],無需複雜的配置安裝過程即可以開發和使用 Knative 應用。
首先我們利用 WAGI 來定義一個 Knative 服務:
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: autoscale-wagi
namespace: default
spec:
template:
metadata:
annotations:
# Knative concurrency-based autoscaling (default).
autoscaling.knative.dev/class: kpa.autoscaling.knative.dev
autoscaling.knative.dev/metric: concurrency
# Target 10 requests in-flight per pod.
autoscaling.knative.dev/target: "10"
# Disable scale to zero with a min scale of 1.
autoscaling.knative.dev/min-scale: "1"
# Limit scaling to 100 pods.
autoscaling.knative.dev/max-scale: "10"
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/denverdino/knative-wagi:0.8.1-with-cache
其中:
-
容器映象 knative-wagi 包含了 WAGI 閘道器和一些示例的 WASI 應用,更多細節可以參考專案[7]。
-
autoscale-wagi 服務可以根據請求數進行彈性伸縮
$ kubectl apply -f knative_test.yaml
$ kubectl get ksvc autoscale-wagi NAME URL LATESTCREATED LATESTREADY READY REASON autoscale-wagi http://autoscale-wagi.default.127.0.0.1.sslip.io autoscale-wagi-00002 autoscale-wagi-00002 True $ curl http://autoscale-wagi.default.127.0.0.1.sslip.io Oh hi world $ curl http://autoscale-wagi.default.127.0.0.1.sslip.io/hello hello world
大家也可以進行一些壓測,學習一下 Knative 的彈性伸縮能力。
後記
本文介紹了 WAGI 這個專案,它可以將 HTTP 伺服器的網路處理細節,與 WASM 應用邏輯實現解耦。這樣可以輕鬆將 WASM/WASI 應用與 Knative 這樣的 Serverless 框架相結合。一方面我們可以複用 Knative/K8s 帶來的彈性和大規模資源排程能力,一方面我們可以發揮 WebAssembly 帶來的安全隔離、可移植、輕量化等優勢。
一脈相承的思考,在之前一篇文章《WebAssembly + Dapr = 下一代雲原生執行時?》 中,我介紹了一個思路是將 WASM 應用與外部服務依賴通過 Dapr 實現解耦,來解決可移植性與多樣化的服務能力之間的矛盾。
當然這些工作還是簡單的玩具,只是用來驗證技術的可能性邊界。主要目的還是拋磚引玉,聽到大家關於下一代分散式應用框架和執行時環境的思考和設想。
文章書寫過程中,忽然回憶起在 90 年代與師兄們一起根據 RFC 規範來實現 HTTP Server 與 CGI Gateway 的歲月,那是一種非常簡單而單純的快樂。在這裡,也祝每一位技術人永葆好奇,享受每一天的程式設計時光。
點選此處,瞭解阿里雲 Serverless 容器服務 ASK 更多詳情!
原文連結:http://click.aliyun.com/m/1000348659/
本文為阿里雲原創內容,未經允許不得轉載。
- 15M安裝包就能玩《原神》,帶你瞭解雲遊戲背後的技術祕密
- 主流定時任務解決方案全橫評
- 面向中後臺複雜場景的低程式碼實踐思路
- PolarDB-X 全域性二級索引
- 微服務治理熱門技術揭祕:無損上線
- 「技術人生」第9篇:如何設定業務目標
- 資料庫治理的探索與實踐
- 一個開發者自述:我是如何設計針對冷熱讀寫場景的 RocketMQ 儲存系統
- 全鏈路壓測:影子庫與影子表之爭
- 阿里雲中間件開源往事
- 阿里雲易立:雲原生如何破解企業降本提效難題?
- 雲原生混部最後一道防線:節點水位線設計
- 照妖鏡:一個工具的自我超越
- 將 Terraform 生態粘合到 Kubernetes 世界
- EventBridge 在 SaaS 企業整合領域的探索與實踐
- 全鏈路壓測:影子庫與影子表之爭
- 當 Knative 遇見 WebAssembly
- 【USENIX ATC】支援異構GPU叢集的超大規模模型的高效的分散式訓練框架Whale
- 千萬級可觀測資料採集器--iLogtail程式碼完整開源
- 設計穩定的微服務系統時不得不考慮的場景