天天看點

openGauss+Wasm:建構安全高效的UDF執行引擎

很多人聽說 WebAssembly,或者它的簡稱 Wasm,可能還是由于它在浏覽器中得到了廣泛的應用。 但是,近些年随着 Wasm 持續不斷的發展,其在伺服器端的應用也越來越廣泛。 在剛剛過去的 10 月底,Docker 釋出了 Docker+Wasm 的技術預覽版本,旨在為廣大開發者提供一個更快速便捷地建構 Wasm 應用程式的容器環境,這一動作标志着 Wasm 在雲原生領域已經得到了有效應用。 那麼,什麼是 Wasm 呢?

openGauss+Wasm:建構安全高效的UDF執行引擎

WebAssemby 是什麼?

先來看看官方的定義:

WebAssembly (abbreviatedWasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.

即 Wasm 是一種基于棧式虛拟機的二進制指令格式,旨在為衆多程式設計語言提供一種可移植的編譯目标,友善應用在 Web 用戶端及伺服器上的部署運作。

Wasm 誕生之初,主要是為了解決前端在複雜業務邏輯場景下,加載和運作緩慢的問題。Wasm 格式的二進制碼體積非常小,可以快速高效地分發和加載,程式執行也非常快,并且由于在設計之初抽象利用的是常見的硬體能力,是以具有非常好的移植性。此外,Wasm 的運作被限制在一個安全的沙箱環境中,是以具有很高的安全性。

随着 Wasm 技術的發展,人們逐漸意識到 Wasm 的可移植、高性能和安全性等特點,在服務端的業務場景中同樣具有巨大的應用價值。于是乎,2019 年,Mozilla、Fastly、Intel  以及 Red Hat  聯合成立位元組碼聯盟(BytecodeAlliance),旨在推動 Wasm 和 WASI(WebAssembly System Interface) 的标準化,以便更好地推廣和完善 Wasm 在服務端的應用場景和技術生态。

為了推廣和增強 Wasm 在服務端的應用,位元組碼聯盟主導孵化了 Wasmtime 項目。該項目提供一個針對 Wasm 位元組碼的獨立的運作時。Wasmtime 具有如下特點:

  • 快速。Wasmtime 基于優化 Cranelift 代碼生成器建構,可在運作時或運作前快速生成高品質的機器代碼。
  • 安全。Wasmtime 的開發非常注重正确性和安全性。在 Rust 運作時安全性保證的基礎上,每個 Wasmtime 的特性都經過 RFC 過程的仔細審查和研究。
  • 可配置。Wasmtime 使用合理的預設值,同時提供豐富的配置項,可以針對 CPU 和記憶體等資源消耗進行更細粒度的控制。
  • WASI 接口豐富。Wasmtime 支援衆多的 WASI 标準接口,可以很友善的和主控端進行通信。
  • 标準相容。Wasmtime 通過了官方的 WebAssembly 測試套件,實作了 Wasm 的官方 C API,并實作了 WebAssembly 中的衆多未來特性。
openGauss+Wasm:建構安全高效的UDF執行引擎

資料庫+Wasm 的嘗試

Wasm 在誕生之初就為自己貼上了高性能和高安全的标簽,而這些也是資料庫系統所一直追求的。資料庫系統如何融入 Wasm 技術,使其在資料庫領域發揮其價值魅力,也成為了很多開發人員探索的一個方向。

cunchydata 的開發人員,基于 v86 模拟器,将 PostgreSQL 整體率先成功地運作在浏覽器之上,并基于此推出了 Web 上的操作平台,最終在 GitHub 上發展成一個高人氣的開源項目。

Wasmer 的開發人員基于 Wasmer 的運作時,使用 Rust 語言為 PostgreSQL 開發了一個 Wa sm 插件,使得在 PostgreSQL 中可以成功運作 Wa sm 位元組碼。該插件為 PostgreSQL 提供了一種運作 Wa sm 建立 UDF 函數,即使用者定義函數的能力,開發人員可以将自己開發的 UDF 函數編譯為 Wa sm 二進制後導入 PostgreSQL 中運作。該項目僅支援 PG10 版本,且在 Wa sm 類型上僅支援整數類型,并且該項目已經有兩年多沒有更新過了。

最近 SQLite 的開發人員,基于 Wasmtime 運作時,成功的為 SQLite 開發支援了 Wa sm 函數的能力,并已經合入 SQLite 社群。開發人員在 SQLite 中建立了新的函數表,提供了新的建立 UDF 函數的語言 Wa sm 的文法,這樣使用者可以直接使用 create function function_name language wasm 的形式為SQLite 增加 UDF 函數。但是該方式無法批量導入開發人員開發的 Wa sm 函數,且 Wa sm 語言的表現形式比較差,普通使用者無法直覺的了解函數簽名等重要資訊,不便于使用者使用 Wa sm 函數。在函數調用時,在确定函數不存在于 SQLite 系統中時,才會去新增的函數表中查找該函數,這樣的二次查找方式也會造成部分性能損耗。

openGauss+Wasm:建構安全高效的UDF執行引擎

openGauss 與 Wasm 的融合

在簡單調研了 Wasm 的現狀後,我們基于 Wasmtime 的運作時,為 openGauss 開發了一套獨立的 UDF 函數執行引擎 WasmExecutor,下面就來詳細看看這個 UDF 引擎是如何工作的。

WasmExecutor 總體架構

openGauss+Wasm:建構安全高效的UDF執行引擎

上圖便是我們設計的 UDF 執行引擎的結構圖。基于 openGauss 提供的良好的擴充接口,我們插件化地實作了 Wasm 版本的 UDF 執行引擎 WasmExecutor,這種插件化方式可以避免對 openGauss 核心代碼的侵入修改,保持版本的獨立演進。

如結構圖所示,開發人員可以使用自己喜歡的程式設計語言來設計開發 UDF 函數,開發完成後将函數編譯為 Wasm 形式的二進制目标碼,就可以通過 WasmExecutor 引擎提供的能力将 UDF 函數內建到 openGauss 資料庫中。在此之後,使用者便可以像使用内置函數一樣,使用新增的 UDF 函數了。

為了實作将 Wasm 檔案中的函數導入到 openGauss 的能力,我們開發了加載子產品。該子產品提供兩個函數 wasm_new_instance(absolutepath: text, namespace: text) 和 wasm_new_instance_wat(absolutepath: text, namespace: text),其中第一個參數用來指定待導入 Wa sm 檔案的絕對路徑,第二個參數用來指定函數将導入的名稱空間。之是以設定第二個參數,是友善人們進行函數管理,避免函數名稱沖突,最終使用者在 SQL 調用時提供的函數名稱為 namespace_funcname 的新名稱。顧名思義,Wat 字尾的加載函數用來加載 Wat 格式的函數檔案。加載子產品會對提供的 Wa sm 檔案進行基本效驗,然後調用 Wa sm 的 runtime 接口來加載解析 Wa sm 檔案,将解析結果儲存在運作時管理中。

運作時管理主要實作加載到記憶體中 Wa sm 檔案的管理工作,并且為每個加載的 Wa sm 檔案,基于檔案絕對路徑計算一個哈希值,作為該檔案的 uuid 使用。運作時管理提供名為 wasm.instances 的元資訊表,使用者可以查詢該表獲得目前系統中建立的 wasm 執行個體資訊。

函數管理子產品主要實作 Wa sm 檔案中導出的函數與 openGauss 核心的綁定,每一個 Wa sm 導出函數都會綁定到對應的公共接口上,以便使用者通過 SQL 文法可以直接調用。函數管理子產品提供名為 wasm.exported_functions 的元資訊表,使用者可以查詢該表擷取目前系統中已經導出的 Wa sm 函數資訊。

下圖所示即為調用加載函數加載新的 Wa sm 檔案時的流程示意圖。

openGauss+Wasm:建構安全高效的UDF執行引擎

實操示範

下面我們實際操作下,如何通過 WasmExecutor 引擎來加載執行 Wa sm 格式的 UDF 函數。為了友善夥伴們快速體驗,我們提供了支援 WasmExecutor 引擎的容器鏡像,釋出于 opengaussofficial 組織下,大家可以通過以下方式擷取和運作該容器鏡像

容器啟動成功後,登入 openGauss 資料庫,建立 WasmExecutor 引擎,如下:

openGauss+Wasm:建構安全高效的UDF執行引擎

在容器鏡像中,我們預設内置了一些 Wa sm 和 Wat 格式的示例檔案,供夥伴們快速上手體驗,這些檔案放置于 /home/opengauss 路徑下,如下所示

openGauss+Wasm:建構安全高效的UDF執行引擎

如下,我們使用 wasm_new_instance 和 wasm_new_instance_wat 來分别加載 sum.wasm 和 fib.wat 中的函數,在加載函數檔案時,提供函數放置的名稱空間 namespace,友善進行函數管理,最終注冊到 openGauss 系統表中的函數名稱将會是 namespace_funcname 的新名稱。

openGauss+Wasm:建構安全高效的UDF執行引擎

查詢 WasmExecutor 引擎提供的元資訊表,可以直覺地看到目前系統中存在的 Wasm 執行個體資訊和導出的 Wasm 函數資訊:

openGauss+Wasm:建構安全高效的UDF執行引擎

可以看到,通過 wasm.exported_functions 元資訊表,可以友善地查詢導出的函數簽名,友善函數調用者使用,導出的函數和 openGauss 内置的函數一樣,支援使用原生 SQL 來調用,如下所示:

openGauss+Wasm:建構安全高效的UDF執行引擎

性能測試對比

為了對 Wasm 的執行性能做一個直覺的展示,我們在一台 4U 8G 的雲虛拟機上進行了簡單的性能測試。我們使用 Wasm 和 pl/pgsql 分别進行斐波那契數列的計算,測得的結果如下所示。

openGauss+Wasm:建構安全高效的UDF執行引擎

可以看出,即便在計算量比較小的場景下,Wasm 的執行性能也明顯優于 pl/pgsql,随着計算量的增長,Wasm 的執行性能已經遠遠高于 pl/pgsql。由此可以看出,Wasm 在計算密集型的資料庫應用場景下具有非常吸引人的應用潛力。

openGauss+Wasm:建構安全高效的UDF執行引擎

未來展望

Wasm 技術正在如火如荼的發展着,随着 WASI 接口的不斷豐富和完善,其在服務端的應用能力也将越來越成熟。openGauss 作為領先的企業級資料庫,未來也将持續不斷的跟進和融合 Wasm 的發展成果,提升 openGauss 資料庫的安全性和性能。

目前提供的 openGauss+Wasm 的能力版本還隻是個原型版本,項目還在努力開發中,後續将會支援更多的資料類型和資料庫操作能力,希望更多感興趣的小夥伴能夠加入我們,與我們一起打造領先的資料庫引擎。

最後歡迎各位夥伴加入 openGauss 社群,與我們一起探索 openGauss 的應用場景,共建 openGauss 資料庫生态。

參考連結

  • https://webassembly.org/
  • https://bytecodealliance.org/
  • https://www.crunchydata.com/blog/crazy-idea-to-postgres-in-the-web-
  • https://www.crunchydata.com/developers/playground [5] https://github.co m/snaplet/postgres-wasm
  • https://github.com/libsql/libsql/pull/45#event-7860356368

本文轉自CSDN

◆ 推薦閱讀◆

openGauss+Wasm:建構安全高效的UDF執行引擎

@資料庫er,openGauss Summit 2022 喊您來參會啦!

本文分享自微信公衆号 - openGauss(openGauss)。

如有侵權,請聯系 [email protected] 删除。

本文參與“ OSC源創計劃 ”,歡迎正在閱讀的你也加入,一起分享。

繼續閱讀