lua-resty-balancer
OpenResty/Lua 的通用一致性哈希实现
$ opm get jojohappy/lua-resty-balancer
名称
lua-resty-chash - OpenResty/LuaJIT 的通用一致性哈希实现
lua-resty-roundrobin - OpenResty/LuaJIT 的通用轮询实现
状态
此库仍处于早期开发阶段,尚处于实验阶段。
描述
此 Lua 库可与 balancer_by_lua*
一起使用。
概要
lua_package_path "/path/to/lua-resty-chash/lib/?.lua;;";
lua_package_cpath "/path/to/lua-resty-chash/?.so;;";
init_by_lua_block {
local resty_chash = require "resty.chash"
local resty_roundrobin = require "resty.roundrobin"
local server_list = {
["127.0.0.1:1985"] = 2,
["127.0.0.1:1986"] = 2,
["127.0.0.1:1987"] = 1,
}
-- XX: we can do the following steps to keep consistency with nginx chash
local str_null = string.char(0)
local servers, nodes = {}, {}
for serv, weight in pairs(server_list) do
-- XX: we can just use serv as id when we doesn't need keep consistency with nginx chash
local id = string.gsub(serv, ":", str_null)
servers[id] = serv
nodes[id] = weight
end
local chash_up = resty_chash:new(nodes)
package.loaded.my_chash_up = chash_up
package.loaded.my_servers = servers
local rr_up = resty_roundrobin:new(server_list)
package.loaded.my_rr_up = rr_up
}
upstream backend_chash {
server 0.0.0.1;
balancer_by_lua_block {
local b = require "ngx.balancer"
local chash_up = package.loaded.my_chash_up
local servers = package.loaded.my_servers
-- we can balancer by any key here
local id = chash_up:find(ngx.var.arg_key)
local server = servers[id]
assert(b.set_current_peer(server))
}
}
upstream backend_rr {
server 0.0.0.1;
balancer_by_lua_block {
local b = require "ngx.balancer"
local rr_up = package.loaded.my_rr_up
local server = rr_up:find()
assert(b.set_current_peer(server))
}
}
server {
location /chash {
proxy_pass http://backend_chash;
}
location /roundrobin {
proxy_pass http://backend_rr;
}
}
方法
resty.chash
和 resty.roundrobin
具有相同的 API。
new
语法: obj, err = class.new(nodes)
实例化此类的对象。class
值由调用 require "resty.chash"
返回。
当我们需要与 nginx chash 保持一致性时,id
应为 table.concat({host, string.char(0), port})
,就像 nginx chash 所做的那样。
当我们不需要与 nginx chash 保持一致性时,id
可以是任何字符串值。
local nodes = {
-- id => weight
server1 = 10,
server2 = 2,
}
local resty_chash = require "resty.chash"
local chash = resty_chash:new(nodes)
local id = chash:find("foo")
ngx.say(id)
reinit
语法: obj:reinit(nodes)
使用新的 nodes
重新初始化 chash 对象。
set
语法: obj:set(id, weight)
设置 id
的 weight
。
delete
语法: obj:delete(id)
删除 id
。
incr
语法: obj:incr(id, weight?)
将 id
的权重增加步长值 weight
(默认为 1)。
decr
语法: obj:decr(id, weight?)
将 id
的权重减少步长值 weight
(默认为 1)。
find
语法: id, index = obj:find(key)
通过 key
查找 id,相同的 key 在相同的 obj
中始终返回相同的 id
。
第二个返回值 index
是 key
的哈希值在 chash 循环中的索引。
next
语法: id, new_index = obj:next(old_index)
如果第一个 id
(服务器)无法正常工作时有机会重试,那么我们可以使用 obj:next
获取下一个 id
。
新的 id
可能与旧的相同。
安装
首先,您需要运行 make
生成 librestychash.so。然后,您需要配置 lua_package_path 和 lua_package_cpath 指令,以将 lua-resty-chash 源代码树的路径添加到 ngx_lua 的 LUA_PATH 搜索路径中,如下所示
# nginx.conf
http {
lua_package_path "/path/to/lua-resty-chash/lib/?.lua;;";
lua_package_cpath "/path/to/lua-resty-chash/?.so;;";
...
}
确保运行 Nginx“worker”进程的系统帐户具有读取 .lua
和 .so
文件的足够权限。
性能
有一个基准测试脚本 t/bench.lua
。
当我运行 make bench
时,我得到了结果
chash new servers
10000 times
elasped: 0.61600017547607
chash new servers2
1000 times
elasped: 0.77300000190735
chash new servers3
10000 times
elasped: 0.66899991035461
new in func
10000 times
elasped: 0.62000012397766
new dynamic
10000 times
elasped: 0.75499987602234
incr server3
10000 times
elasped: 0.19000029563904
incr server1
10000 times
elasped: 0.33699989318848
decr server1
10000 times
elasped: 0.27300024032593
delete server3
10000 times
elasped: 0.037999868392944
delete server1
10000 times
elasped: 0.065000057220459
set server1 9
10000 times
elasped: 0.26600003242493
set server1 8
10000 times
elasped: 0.32000017166138
set server1 1
10000 times
elasped: 0.56699991226196
base for find
1000000 times
elasped: 0.01800012588501
find
1000000 times
elasped: 0.9469997882843
作者
朱德江 (doujiang24) <doujiang24@gmail.com>。
版权和许可
此模块根据 BSD 许可证许可。
版权所有 (C) 2015-2016,由张亦春 (agentzh) <agentzh@gmail.com>,CloudFlare Inc。
保留所有权利。
在满足以下条件的情况下,允许以源代码和二进制形式重新分发和使用,无论是否修改:
源代码的重新分发必须保留上述版权声明、此条件列表和以下免责声明。
二进制形式的重新分发必须在随分发提供的文档和/或其他材料中复制上述版权声明、此条件列表和以下免责声明。
本软件由版权持有人和贡献者“按原样”提供,并且任何明示或暗示的保证,包括但不限于适销性和特定用途适用性的暗示保证,均不予以保证。在任何情况下,版权持有人或贡献者均不对任何直接、间接、附带、特殊、惩罚性或后果性损害(包括但不限于替代商品或服务的采购;使用、数据或利润损失;或业务中断),无论这些损害是如何造成的,以及在任何责任理论下,无论是合同、严格责任还是侵权行为(包括疏忽或其他原因)都与本软件的使用有关,即使已被告知此类损害的可能性。
另请参阅
ngx_lua 模块:http://wiki.nginx.org/HttpLuaModule
Lua 和 C 的 json 库:https://github.com/cloudflare/lua-resty-json
作者
jojohappy
许可证
mit
版本
-
OpenResty/Lua 的通用一致性哈希实现 2018-10-18 09:13:54