本文介紹 Higress 將 Wasm 外掛的執行時從 V8 切換到 WebAssembly Micro Runtime (WAMR) 的最新進展。透過切換到 WAMR 並開啟 AOT 模式大幅提升了 Wasm 外掛效能,從我們的測試中大部分外掛平均有 50% 左右的效能提升,一些邏輯複雜的外掛效能直接翻倍。
Higress Wasm 外掛
Higress 作為首個推出 Wasm 擴充套件能力的雲產品閘道器,從 2022 年就上線了 Wasm 外掛市場,我們使用 Wasm 技術作為主要的閘道器擴充套件手段,是因為它能為使用者帶來的獨特價值:
1. 工程可靠性:相比 Lua 等動態型別+解釋執行語言,Wasm 可基於多種靜態型別語言編譯,可以做編譯期檢查,避免執行時出錯把生產環境變成程式碼捉蟲現場。
2. 沙箱安全性:Wasm 外掛執行在嚴格的虛擬機器沙箱環境內,有自己的獨立記憶體空間,不能直接訪問外部記憶體,可以避免外掛程式碼 bug 導致遭到緩衝區溢位、遠端程式碼執行等攻擊。
3. 熱更新:Higress 基於 Envoy 的 xDS 機制,外掛二進位制和配置都可以獨立熱更新,不會引起連線斷開,對 WebSocket/gRPC 等業務場景更友好。
Higress 站在 Istio/Envoy 的肩膀上,為 Wasm 外掛機制增加了三個核心能力:
1. 域名/路由級生效:Istio/Envoy 自帶的全域性生效方式難以滿足大部分場景需求,而基於 Higress Wasm sdk 開發的外掛可以做到這點,同時編譯出的外掛也跟 Istio/Envoy 生態相容(僅全域性生效)。
2. Redis 訪問能力:提供了訪問 Redis 的 Host Function,外掛程式碼可以基於 Redis 實現多種能力,例如全侷限流,Session 狀態管理等。
3. 虛擬機器自愈機制:開發的外掛邏輯中若出現了空指標訪問、陣列越界、記憶體洩漏等問題,將被執行時系統捕獲,不會導致閘道器崩潰;Higress 支援 Wasm 模組異常後自動重啟,並能在快速止血的同時,透過告警通知使用者出現問題的程式碼堆疊。
從 Higress 的企業使用者看 Wasm 外掛技術的採用週期,已經跨域過鴻溝,步入早期採用大眾階段,核心的驅動力是效能紅利帶來的成本下降。使用者使用 Wasm 外掛來開發滿足自己特定業務需求的能力,對於鑑權、加解密、會話管理等邏輯在閘道器完成計算資源的解除安裝,無需後端服務處理,從而全域性降低計算成本。
效能資料上,之前發表的這篇文件《透過Higress Wasm外掛3倍效能實現Spring Cloud Gateway功能》反饋了過去的效能成果。
在 Higress 將 Wasm 執行時從 V8 替換為 WAMR 後,Wasm 外掛的效能對比之前又有了大幅提升。
Wasm 執行時升級:從 V8 到 WAMR
V8 存在的問題
Wasm 技術誕生於瀏覽器場景,作為 Chromium 的 JS 引擎,V8 是最早支援 Wasm 的執行時之一,V8 引擎基於 JIT 模式執行 Wasm 模組,有著很好的效能。但也存在以下問題:
1. V8 專案複雜度很高:Wasm 相關實現跟 JS 處理邏輯有較多耦合,比如早期的 Envoy Wasm 外掛的一個 bug 就是 V8 為最佳化 JS 執行記憶體引入指標壓縮導致。
bug:https://bugs.chromium.org/p/v8/issues/detail?id=12592
2. V8 社群和 Envoy 社群之間缺少協作:Envoy 目前對於 V8 的版本依賴還停留在 2022 年的提交,無法支援 Wasm GC 等新特性,因為專案複雜度高,升級 V8 依賴的風險也很高。
3. 客戶端偏好:V8 的使用者和開發者大多來自客戶端,考慮裝置相容性,更重視 JIT 模式的最佳化,AOT 模式下效能提升不大,無法完全發揮 Wasm 效能優勢。
WAMR 的優勢
WAMR 是最早由 Intel 團隊開發,在位元組碼聯盟(Bytecode Alliance,面向 Wasm 軟體生態的非盈利組織)下的一個廣受歡迎的 WebAssembly 執行時開源專案。目前社群活躍的貢獻者包含來自 Intel、小米、亞馬遜、索尼、Midokura、西門子、螞蟻等公司的工程師。WAMR 使用 C 語言開發,具有良好的平臺適應性。支援解釋模式、即時編譯及預編譯等模式執行 Wasm 模組,有著優良的效能,在多個公開效能測評報告中均表現優異,同時又極低的資源開銷,可以在 100KB 記憶體中執行單個 Wasm 例項。
效能對比
- 壓測工具:k6
- 伺服器 CPU 型號:Intel(R) Xeon(R) Platinum 8369B CPU @ 2.90GHz
- 壓測方式:Higress 啟動 2 個 worker 執行緒,壓測期間固定 k6 的壓力,跑滿兩個執行緒
選取了部分 Higress 外掛進行效能測試,情況如下:
外掛名稱 | 外掛用途 | V8 (ms) |
WAMR (ms) |
效能提升 |
bot-detect | 基於正則識別阻止網際網路爬蟲對站點資源的爬取 | 1.25 | 0.64 | 95% |
hmac-auth | 基於HMAC演算法為HTTP請求生成不可偽造的簽名, 並基於簽名實現身份認證和鑑權 |
4.44 | 3.25 | 36% |
jwt-auth | 基於JWT(JSON Web Tokens)進行認證鑑權 | 11.98 | 7.46 | 60% |
jwt-logout | 基於Redis實現JWT的弱狀態管理,解決JWT無法登出的問題 | 14.08 | 8.44 | 66% |
key-auth | 基於 API Key 進行認證鑑權 | 1.66 | 1.16 | 43% |
oauth | 基於JWT進行OAuth2 Access Token簽發 | 10.15 | 4.75 | 113% |
注:表格中的資料為單請求平均附加延時
整體來看,Wasm 指令越複雜的外掛,WAMR 的提升越明顯。上述所有外掛除 jwt-logout 是企業版外掛未開源以外,其餘外掛均可以在 Higress 開源倉庫目錄下檢視對應原始碼實現:https://github.com/alibaba/higress/tree/main/plugins/wasm-cpp/extensions
編譯生成 AOT 檔案,可以使用 wamrc 這個 WAMR 提供的官方編譯工具:wamrc --invoke-c-api-import -o plugin.aot plugin.wasm。
為了生成的 wasm 檔案可以相容 JIT 模式,使用 WAMR 倉庫下的指令碼生成合並檔案:python3 wasm-micro-runtime/test-tools/append-aot-to-wasm/append_aot_to_wasm.py --aot plugin.aot --wasm plugin.wasm -o plugin.aot.wasm
以提升最大的 oauth 外掛為例,可以使用下述配置進行復現:
k6 壓測命令:k6 run --vus 300 ./script.js --duration 60s
k6 壓測指令碼:
import http from 'k6/http';
import { check } from 'k6';
export default function () {
const res = http.get('http://11.164.3.16:10000/',{headers: {'Authorization':'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6ImFwcGxpY2F0aW9uL2F0K2p3dCJ9.eyJhdWQiOiJ0ZXN0MiIsImNsaWVudF9pZCI6Ijk1MTViNTY0LTBiMWQtMTFlZS05YzRjLTAwMTYzZTEyNTBiNSIsImV4cCI6MTY2NTY3MzgyOSwiaWF0IjoxNjY1NjczODE5LCJpc3MiOiJIaWdyZXNzLUdhdGV3YXkiLCJqdGkiOiIxMDk1OWQxYi04ZDYxLTRkZWMtYmVhNy05NDgxMDM3NWI2M2MiLCJzY29wZSI6InRlc3QiLCJzdWIiOiJjb25zdW1lcjEifQ.LsZ6mlRxlaqWa0IAZgmGVuDgypRbctkTcOyoCxqLrHY'}});
check(res, { 'status was 200': (r) => r.status == 200 });
}
envoy 配置片段:
- name: envoy.filters.http.wasm
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
config:
name: "my_plugin"
configuration:
"@type": "type.googleapis.com/google.protobuf.StringValue"
value: |
{
"consumers": [
{
"name": "consumer1",
"client_id": "9515b564-0b1d-11ee-9c4c-00163e1250b5",
"client_secret": "9e55de56-0b1d-11ee-b8ec-00163e1250b5"
}
],
"clock_skew_seconds": 3153600000
}
vm_config:
runtime: envoy.wasm.runtime.wamr
#runtime: envoy.wasm.runtime.v8
code:
local:
filename: "oauth.aot.wasm"
allow_precompiled: true
效能提升原因
主要的原因包含:
1. WAMR 提供了深度最佳化的預編譯的能力。在部署前,WAMR 將 Wasm opcodes 翻譯為 IR,經過定製的最佳化流水線,生成指定平臺的機器碼。在執行時,執行預編譯後的 Wasm 可以獲得媲美 native binary 的效能。
2. WAMR 採用了高度最佳化的 FFI。有效降低在 host(c/c++) 和 guest(wasm) 兩個世界間“穿梭”時需要的型別轉換和記憶體複製的次數,減少不必要的損耗。
3. WAMR 可以智慧感知平臺的硬體加速能力並予以充分利用。比如當執行在 X86 平臺時,WAMR 實現了學術界最新提出的 "segue" 演算法,利用 GS 暫存器作為定址方法,提升了訪問 Wasm 線性空間的效率。
未來展望
在 Higress 團隊和 WAMR 團隊之間的緊密協作下,除了在閘道器場景提升 Wasm 外掛效能,還帶來了很多實用的新特性即將釋出,敬請期待:
1. 支援生成 CPU 火焰圖,例如下面是 Wasm 外掛中執行 fibonacci 遞迴看到的 CPU 火焰圖:
2. 支援 Wasm 外掛中邏輯問題導致 Crash 後,外掛日誌中列印完整的函式堆疊,並可以透過 WAMR 提供的 addr2line 工具定位到原始碼中的具體行號。
3. 支援觀測每個 Wasm 外掛模組的 CPU 和記憶體佔用情況。
4. 支援使用 TypeScript 編寫 Wasm 外掛,完整語法支援。
歡迎更多開發者一起參與 Higress 和 WAMR 開源社群,GitHub 專案地址:
Higress:https://github.com/alibaba/higress
WAMR:https://github.com/bytecodealliance/wasm-micro-runtime
本文作者:
澄潭,阿里雲 API 閘道器軟體工程師,Higress 開源專案主要貢獻者
何良,Intel Web Platform Engineering 軟體工程師,WAMR 開源專案主要貢獻者
原文連結
本文為阿里雲原創內容,未經允許不得轉載。