lua-resty-radixtree
opm 包 => 基于 FFI 的 rax Lua 实现库。
$ opm get xiangnanscu/lua-resty-radixtree
用于 openresty 默认安装
make && INST_PREFIX=/usr/local/openresty/luajit make install
名称
这是一个基于 FFI 的 rax Lua 实现库。
[!构建状态](https://travis-ci.org/iresty/lua-resty-radixtree) [!许可证](https://github.com/iresty/lua-resty-radixtree/blob/master/LICENSE)
此项目依赖于 lua-resty-ipmatcher 和 lua-resty-expr。
此项目已在微服务 API 网关 Apache APISIX 中使用。
该项目由 深圳市智柳科技有限公司 开源。
除了这个开源版本外,我们公司还提供更强大和高效的商业版本,并提供技术支持。如果您对我们的商业版本感兴趣,请联系 我们。
概要
location / {
content_by_lua_block {
local radix = require("resty.radixtree")
local rx = radix.new({
{
paths = {"/aa", "/bb*", "/name/:name/*other"},
hosts = {"*.bar.com", "foo.com"},
methods = {"GET", "POST", "PUT"},
remote_addrs = {"127.0.0.1","192.168.0.0/16",
"::1", "fe80::/32"},
vars = {
{"arg_name", "==", "json"},
{"arg_weight", ">", 10},
},
filter_fun = function(vars, opts)
return vars["arg_name"] == "json"
end,
metadata = "metadata /bb",
}
})
-- try to match
local opts = {
host = "foo.com",
method = "GET",
remote_addr = "127.0.0.1",
vars = ngx.var,
}
ngx.say(rx:match("/aa", opts))
-- try to match and store the cached value
local opts = {
host = "foo.com",
method = "GET",
remote_addr = "127.0.0.1",
vars = ngx.var,
matched = {}
}
ngx.say(rx:match("/name/json/foo/bar/gloo", opts))
ngx.say("name: ", opts.matched.name, " other: ", opts.matched.other)
}
}
方法
new
语法: rx, err = radix.new(routes, opts)
routes 是一个数组表,例如 { {...}, {...}, {...} }
,数组中的每个元素都是一条路由,是一个哈希表。
每个元素的属性可能包含以下内容:
|名称 |选项 |描述|示例| |:-------- |:--------|:-----------|:-----| |paths |必需|客户端请求路径列表。默认情况下是完全匹配,但如果路径的末尾是 *
,则表示这是一个前缀路径。例如 /foo*
,它将匹配 /foo/bar
或 /foo/glo/grey
等|{"/", "/aa", "/bb"}| |hosts |选项 |客户端请求主机列表,不仅支持普通域名,还支持通配符名称。|{"foo.com", "*.bar.com"}| |remote_addrs|选项 |客户端远程地址(IPv4 和 IPv6) 列表,可以使用 CIDR 格式,例如 192.168.1.0/24
。|{"127.0.0.1", "192.0.0.0/8", "::1", "fe80::/32"}| |methods |选项 |方法名称列表。以下是完整有效的 方法列表:"GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "CONNECT" 和 "TRACE"。|{"GET", "POST"}| |vars |选项 |使用给定的 opts.vars
或 ngx.var
来评估的 DSL。请参阅 https://github.com/api7/lua-resty-expr#new |{{"arg_name", "==", "json"}, {"arg_age", ">", 18}}| |filter_fun |选项 |用户定义的过滤器函数,可以用来实现特殊场景的匹配逻辑。radixtree
在匹配路由时会传递 vars
和其他参数。|function(vars) return vars["arg_name"] == "json" end| |priority |选项 |路由优先级,默认为 0。|priority = 100| |metadata |选项 |如果使用 rx:match
来匹配路由,则将返回此字段。|| |handler |选项 |使用 rx:dispatch
来匹配路由时将调用此函数。||
opts
是一个可选的配置,用于控制匹配的行为。支持以下字段:
|名称 |描述|默认值| |:-------- |:-----------|:-----| |no_param_match|禁用 "路径中的参数"|false|
路径
local rx = radix.new({
{
paths = {"/aa", "/bb/cc", "/dd/ee/index.html"},
metadata = "metadata /aa",
},
{
paths = {"/gg"},
metadata = "metadata /gg",
},
{
paths = {"/index.html"},
metadata = "metadata /index.html",
},
})
完全路径匹配
完全路径匹配,允许同时指定多个路径。
local rx = radix.new({
{
paths = {"/aa/*", "/bb/cc/*"},
metadata = "metadata /aa",
},
{
paths = {"/gg/*"},
metadata = "metadata /gg",
},
})
前缀匹配
路径前缀匹配,允许同时指定多个路径。
local rx = radix.new({
{
-- This handler will match /user/john but will not match /user/ or /user
paths = {"/user/:user"},
metadata = "metadata /user",
},
{
-- However, this one will match /user/john/ and also /user/john/send/data
paths = {"/user/:user/*action"},
metadata = "metadata action",
},
})
路径中的参数
match
语法: metadata = rx:match(path, opts)
path
: 客户端请求路径。opts
: 一个 Lua 表 (可选)。method
: 可选,客户端请求的方法名称。host
: 可选,客户端请求主机。remote_addr
: 可选,客户端远程地址,例如192.168.1.100
。paths
: 可选,客户端请求路径列表。
vars
: 可选,一个用于获取变量的 Lua 表,默认值为 ngx.var
,用于获取 Nginx 内置变量。
local metadata = rx:match(ngx.var.uri, {...})
根据 method
、path
和 host
等匹配路由,如果成功则返回 metadata
。
dispatch
语法: metadata = rx:match(path, opts)
path
: 客户端请求路径。opts
: 一个 Lua 表 (可选)。method
: 可选,客户端请求的方法名称。host
: 可选,客户端请求主机。paths
: 可选,客户端请求路径列表。
语法: ok = rx:dispatch(path, opts, ...)
local ok = rx:dispatch(ngx.var.uri, {...})
根据 method
、path
和 host
等匹配路由,如果成功则调用 handler
函数。
安装
make install
编译并安装
开发环境
make deps
安装依赖项
基准测试
$ make
cc -O2 -g -Wall -fpic -std=c99 -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -DBUILDING_SO -c src/rax.c -o src/rax.o
cc -O2 -g -Wall -fpic -std=c99 -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -DBUILDING_SO -c src/easy_rax.c -o src/easy_rax.o
cc -shared -fvisibility=hidden src/rax.o src/easy_rax.o -o librestyradixtree.so
$ make bench
resty -I=./lib -I=./deps/share/lua/5.1 benchmark/match-parameter.lua
matched res: 1
route count: 100000
match times: 10000000
time used : 3.1400001049042 sec
QPS : 3184713
each time : 0.31400001049042 ns
resty -I=./lib -I=./deps/share/lua/5.1 benchmark/match-prefix.lua
matched res: 500
route count: 100000
match times: 1000000
time used : 0.42700004577637 sec
QPS : 2341920
resty -I=./lib -I=./deps/share/lua/5.1 benchmark/match-static.lua
matched res: 500
route count: 100000
match times: 10000000
time used : 0.95000004768372 sec
QPS : 10526315
resty -I=./lib -I=./deps/share/lua/5.1 benchmark/match-hosts.lua
matched res: 500
route count: 1000
match times: 100000
time used : 0.60199999809265 sec
QPS : 166112
resty -I=./lib -I=./deps/share/lua/5.1 benchmark/match-wildcard-hosts.lua
matched res: 500
route count: 1000
match times: 50000
time used : 0.47900009155273 sec
QPS : 104384
我们编写了一些简单的基准测试脚本。机器环境:MacBook Pro (16 英寸,2019),CPU 2.3 GHz Intel Core i9。
作者
Nan Xiang(@xiangnanscu)
许可证
apache2
依赖项
xiangnanscu/lua-resty-expr, xiangnanscu/lua-resty-ipmatcher
-
opm 包 => 基于 FFI 的 rax Lua 实现库。 2022-01-11 16:18:15
-
opm 包 => 基于 FFI 的 rax Lua 实现库。 2021-06-15 07:10:50