?架構(gòu)如上圖所示
Lua-resty-ffi提供了一個高效和通用的API,用于使用主流語言(go、Python/ target=_blank class=infotextkey>Python、JAVA、Rust等)進(jìn)行開放式編程。
因?yàn)槭峭ㄟ^c擴(kuò)展直接調(diào)用因此可以保證性能,對于任何對c擴(kuò)展支持的編程語言都可以快速接入。
?特征介紹
lua-resty-ffi提供了一個高效和通用的API,用于使用主流語言(Go、Python、Java、Rust等)進(jìn)行開放式編程。
特點(diǎn):
- 非阻塞,以協(xié)程方式
- 簡單但可擴(kuò)展的界面,支持任何符合C ABI的語言
- 總的來說,不再需要編寫C/Lua代碼來進(jìn)行耦合
- 高性能,比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
有關(guān)詳細(xì)信息,請查看每種編程語言的目錄。
此外,請查看此博客文章:http://luajit.io/post/implement-grpc-client-in-rust-for-openresty/
該文章講到如何通過rust使用openresty
?背景
在openresty領(lǐng)域,當(dāng)你轉(zhuǎn)向?qū)崿F(xiàn)一些邏輯,特別是與第三方流行框架相結(jié)合時,它可能會很尷尬:沒有對應(yīng)的接入方式。
C是一種低級語言,沒有統(tǒng)一和豐富的庫和生態(tài)系統(tǒng),大多數(shù)現(xiàn)代框架不支持C,相反,它們喜歡Java、Python、Go。C適用于基礎(chǔ)軟件。
Lua是一種嵌入式和最小的編程語言,這意味著所有力量都來自主機(jī)。在開放中,這意味著所有功能都來自lua-nginx模塊。像C一樣,甚至更糟糕的是,你必須通過Cosocket重新發(fā)明車輪,才能做現(xiàn)代網(wǎng)絡(luò)的事情。許多l(xiāng)ua-resty-*誕生了,但與其他語言的母語lib相比,它們幾乎是半成品。例如,lua-resty-kafka不支持消費(fèi)者團(tuán)體,lua-resty-postgres不支持通知和準(zhǔn)備聲明等。此外,lua-resty-*的大多數(shù)作者在某個階段停止了開發(fā),因?yàn)閘ua社區(qū)太小了,吸引力也更小。
?為什么不用wasm
WASM有以下缺點(diǎn),因此不適合開放:
- 沒有協(xié)程,這意味著您需要從頭到尾執(zhí)行邏輯,并以任意時間阻止nginx工作進(jìn)程
- 閹割的語言支持,例如
- Go:你必須使用tinygo,而不是官方golang。
- Rust:您必須使用專用工具集來完成工作,例如,當(dāng)您需要異步網(wǎng)絡(luò)編程時,tokio不可用,相反,您必須使用基于WASI的定制版,例如wasmedge_wasi_socket。
- Python:您必須使用支持WASM的實(shí)現(xiàn),例如rustpython。
- 復(fù)雜的開發(fā),由于沙盒的初衷,您必須從nginx導(dǎo)出大量API
那么,我可以用現(xiàn)代編程語言(Go、Python、Java、Rust等)擴(kuò)展開放性,并直接重用它們豐富的生態(tài)系統(tǒng)嗎?是的,這就是lua-resty-ffi所做的。
?相關(guān)概念
- 擴(kuò)展庫:在Go和Rust中,它意味著編譯的庫,例如libffi_go_etcd.so。
在Python3中,這意味著帶有本機(jī)python3模塊的加載程序庫libffi_python3.so。
在Java中,它意味著帶有原生Java類/jar的加載程序庫libffi_java.so。
- 庫的配置,例如等端口、kafka端口等。
該格式可以是任何序列化格式,例如json、yaml,只要它與運(yùn)行時匹配。
- 運(yùn)行時
庫和配置的組合將引入一個新的運(yùn)行時,該運(yùn)行時代表一些線程或用于執(zhí)行作業(yè)的協(xié)程。
您可以使用具有不同配置的同一庫,這非常常見,特別是對于Java和Python。
- 請求響應(yīng)模式
Nginx工作進(jìn)程和運(yùn)行時之間的耦合基于消息交換,其中包含兩個方向:
1,請求
Lua協(xié)程創(chuàng)造了一項(xiàng)任務(wù)
將任務(wù)與請求消息相關(guān)聯(lián),即C malloc()字符數(shù)組。請注意,這個字符數(shù)組將由lua-resty-ffi釋放,運(yùn)行時只是使用它。
將任務(wù)放入運(yùn)行時的線程安全隊(duì)列并生成
運(yùn)行時輪詢此隊(duì)列
為什么不調(diào)用其他語言提供的API?
在Go中,由于GMP模型,它可能會阻止nginx工作進(jìn)程
它增加了其他語言提供此類API的負(fù)擔(dān)
2,回應(yīng)
運(yùn)行時將響應(yīng)(也稱為C malloc()字符數(shù)組)直接注入ngx_thread_pool_done隊(duì)列,并通過eventfd通知nginx epoll循環(huán),然后nginx將恢復(fù)lua協(xié)程。請注意,lua-resty-ffi將釋放響應(yīng),因此在您的運(yùn)行時無需關(guān)心它。
?壓測
和unix socket domain 對比性能報告如下
?總結(jié)
從事nginx擴(kuò)展開發(fā)的同學(xué)可以關(guān)注下這個擴(kuò)展庫,它開放了一種多語言模型,提供了靈活的擴(kuò)展方式和nginx高性能模型進(jìn)行配合。
項(xiàng)目地址:https://github.com/kingluo/lua-resty-ffi