lua-resty-ffiOpenResty/Nginx 通用接口
lua-resty-ffi提供了一个通用高效的接口,使得你可以使用Go,Python,Java和Rust为 OpenResty/Nginx 直接开发你想要的功能。
众所周知,OpenResty使用的lua和C,生态很弱,很多重造的轮子也缺乏维护,以至于跟外围生态系统互通时,巧妇难为无米之炊。
特色:
- 非阻塞,以协程的方式运行
- 简单可扩展的接口,支持任何符合C ABI的语言
- 一劳永逸,无需再编写任何C或者lua的模块来开发新功能
- 高性能,比unix domain socket要快
- 通用的java、python加载器
- 可使用任何你喜欢的消息序列化格式
最简单的实例:
使用golang开发一个echo功能。
创建文件:echo.go
package main
/*
#cgo LDFLAGS: -shared
#include <string.h>
void* ngx_http_lua_ffi_task_poll(void *p);
char* ngx_http_lua_ffi_get_req(void *tsk, int *len);
void ngx_http_lua_ffi_respond(void *tsk, int rc, char* rsp, int rsp_len);
*/
import "C"
import (
"log"
"unsafe"
)
//export libffi_init
func libffi_init(cfg_cstr *C.char, tq unsafe.Pointer) C.int {
log.Println("start go echo runtime")
go func() {
for {
task := C.ngx_http_lua_ffi_task_poll(tq)
if task == nil {
break
}
var rlen C.int
r := C.ngx_http_lua_ffi_get_req(task, &rlen)
res := C.malloc(C.ulong(rlen))
C.memcpy(res, unsafe.Pointer(r), C.ulong(rlen))
C.ngx_http_lua_ffi_respond(task, 0, (*C.char)(res), rlen)
}
log.Println("exit go echo runtime")
}()
return 0
}
func main() {}
创建文件:nginx.conf
daemon off;
error_log /dev/stderr info;
worker_processes auto;
env LD_LIBRARY_PATH;
events {}
http {
server {
listen 20000;
location /echo {
content_by_lua_block {
local demo = ngx.load_ffi("ffi_go_echo")
local ok, res = demo:echo("foobar")
assert(ok)
assert(res == "foobar")
demo:__unload()
ok, res = demo:echo("foobar")
assert(not ok)
ngx.log(ngx.ERR, res)
ngx.say("ok")
}
}
}
}
运行:
go build -buildmode=c-shared -o libffi_go_echo.so echo.go
LD_LIBRARY_PATH=$(PWD) $(NGINX_BIN) -p $(PWD) -c nginx.conf
curl localhost:20000/echo
评论