?架構如上圖所示
Lua-resty-ffi提供了一個高效和通用的API,用于使用主流語言(go、Python/ target=_blank class=infotextkey>Python、JAVA、Rust等)進行開放式編程。
因為是通過c擴展直接調用因此可以保證性能,對于任何對c擴展支持的編程語言都可以快速接入。
?特征介紹
lua-resty-ffi提供了一個高效和通用的API,用于使用主流語言(Go、Python、Java、Rust等)進行開放式編程。
特點:
- 非阻塞,以協程方式
- 簡單但可擴展的界面,支持任何符合C ABI的語言
- 總的來說,不再需要編寫C/Lua代碼來進行耦合
- 高性能,比unix域套接字方式更快
- Python/java的通用加載程序庫
- 您喜歡的任何序列化消息格式
以go為例
cd /opt
git clone https://github.com/kingluo/lua-resty-ffi
cd lua-resty-ffi
# compile and install openresty with lua-resty-ffi
# optionally, you could specify any compile options you need, e.g.
# ./build.sh --with-pcre-jit --add-module=...
./build.sh
cd examples/go
# install golang if not yet
wget https://go.dev/dl/go1.19.3.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.19.3.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
# compile example libraries
make
# run Nginx
make run
# in another terminal
curl http://localhost:20000/echo
ok
有關詳細信息,請查看每種編程語言的目錄。
此外,請查看此博客文章:http://luajit.io/post/implement-grpc-client-in-rust-for-openresty/
該文章講到如何通過rust使用openresty
?背景
在openresty領域,當你轉向實現一些邏輯,特別是與第三方流行框架相結合時,它可能會很尷尬:沒有對應的接入方式。
C是一種低級語言,沒有統一和豐富的庫和生態系統,大多數現代框架不支持C,相反,它們喜歡Java、Python、Go。C適用于基礎軟件。
Lua是一種嵌入式和最小的編程語言,這意味著所有力量都來自主機。在開放中,這意味著所有功能都來自lua-nginx模塊。像C一樣,甚至更糟糕的是,你必須通過Cosocket重新發明車輪,才能做現代網絡的事情。許多lua-resty-*誕生了,但與其他語言的母語lib相比,它們幾乎是半成品。例如,lua-resty-kafka不支持消費者團體,lua-resty-postgres不支持通知和準備聲明等。此外,lua-resty-*的大多數作者在某個階段停止了開發,因為lua社區太小了,吸引力也更小。
?為什么不用wasm
WASM有以下缺點,因此不適合開放:
- 沒有協程,這意味著您需要從頭到尾執行邏輯,并以任意時間阻止nginx工作進程
- 閹割的語言支持,例如
- Go:你必須使用tinygo,而不是官方golang。
- Rust:您必須使用專用工具集來完成工作,例如,當您需要異步網絡編程時,tokio不可用,相反,您必須使用基于WASI的定制版,例如wasmedge_wasi_socket。
- Python:您必須使用支持WASM的實現,例如rustpython。
- 復雜的開發,由于沙盒的初衷,您必須從nginx導出大量API
那么,我可以用現代編程語言(Go、Python、Java、Rust等)擴展開放性,并直接重用它們豐富的生態系統嗎?是的,這就是lua-resty-ffi所做的。
?相關概念
- 擴展庫:在Go和Rust中,它意味著編譯的庫,例如libffi_go_etcd.so。
在Python3中,這意味著帶有本機python3模塊的加載程序庫libffi_python3.so。
在Java中,它意味著帶有原生Java類/jar的加載程序庫libffi_java.so。
- 庫的配置,例如等端口、kafka端口等。
該格式可以是任何序列化格式,例如json、yaml,只要它與運行時匹配。
- 運行時
庫和配置的組合將引入一個新的運行時,該運行時代表一些線程或用于執行作業的協程。
您可以使用具有不同配置的同一庫,這非常常見,特別是對于Java和Python。
- 請求響應模式
Nginx工作進程和運行時之間的耦合基于消息交換,其中包含兩個方向:
1,請求
Lua協程創造了一項任務
將任務與請求消息相關聯,即C malloc()字符數組。請注意,這個字符數組將由lua-resty-ffi釋放,運行時只是使用它。
將任務放入運行時的線程安全隊列并生成
運行時輪詢此隊列
為什么不調用其他語言提供的API?
在Go中,由于GMP模型,它可能會阻止nginx工作進程
它增加了其他語言提供此類API的負擔
2,回應
運行時將響應(也稱為C malloc()字符數組)直接注入ngx_thread_pool_done隊列,并通過eventfd通知nginx epoll循環,然后nginx將恢復lua協程。請注意,lua-resty-ffi將釋放響應,因此在您的運行時無需關心它。
?壓測
和unix socket domain 對比性能報告如下
?總結
從事nginx擴展開發的同學可以關注下這個擴展庫,它開放了一種多語言模型,提供了靈活的擴展方式和nginx高性能模型進行配合。
項目地址:https://github.com/kingluo/lua-resty-ffi