Higress 全新 Wasm 運行時,性能大幅提升

本文作者:

澄潭,阿里雲 API 網關軟件工程師,Higress 開源項目主要貢獻者

何良,Intel Web Platform Engineering 軟件工程師,WAMR 開源項目主要貢獻者

本文介紹 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

  1. V8 社區和 Envoy 社區之間缺少協作:Envoy 目前對於 V8 的版本依賴還停留在 2022 年的提交,無法支持 Wasm GC 等新特性,因爲項目複雜度高,升級 V8 依賴的風險也很高。

  2. 客戶端偏好: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 火焰圖:

  1. 支持 Wasm 插件中邏輯問題導致 Crash 後,插件日誌中打印完整的函數堆棧,並可以通過 WAMR 提供的 addr2line 工具定位到源代碼中的具體行號。

  2. 支持觀測每個 Wasm 插件模塊的 CPU 和內存佔用情況。

  3. 支持使用 TypeScript 編寫 Wasm 插件,完整語法支持。

歡迎更多開發者一起參與 Higress 和 WAMR 開源社區,GitHub 項目地址:

Higress: https://github.com/alibaba/higress

WAMR: https://github.com/bytecodealliance/wasm-micro-runtime

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