lua-resty-checkups
在纯 ngx_lua 中管理 Nginx 上游
$ opm get firesnow/lua-resty-checkups
名称
lua-resty-checkups - 在纯 ngx_lua 中管理 Nginx 上游
[!构建状态](https://travis-ci.org/upyun/lua-resty-checkups)
状态
在大多数情况下可能已经可以投入生产,但尚未在实际环境中得到验证。请查看问题列表,如果您有任何问题或疑问,请告诉我。
功能
定期向上游服务器发送心跳
主动和被动健康检查
动态上游更新
通过加权轮询或一致哈希进行负载均衡
与 Nginx 上游块同步
按层级或键尝试集群
概述
-- config.lua
_M = {}
_M.global = {
checkup_timer_interval = 15,
checkup_shd_sync_enable = true,
shd_config_timer_interval = 1,
}
_M.ups1 = {
cluster = {
{
servers = {
{host="127.0.0.1", port=4444, weight=10, max_fails=3, fail_timeout=10},
}
},
},
}
return _M
-- nginx.conf
lua_package_path "/path/to/lua-resty-checkups/lib/?.lua;/path/to/config.lua;;";
lua_shared_dict state 10m;
lua_shared_dict mutex 1m;
lua_shared_dict locks 1m;
lua_shared_dict config 10m;
server {
listen 12350;
return 200 12350;
}
server {
listen 12351;
return 200 12351;
}
init_worker_by_lua_block {
local config = require "config"
local checkups = require "resty.checkups.api"
checkups.prepare_checker(config)
checkups.create_checker()
}
server {
location = /12350 {
proxy_pass http://127.0.0.1:12350/;
}
location = /12351 {
proxy_pass http://127.0.0.1:12351/;
}
location = /t {
content_by_lua_block {
local checkups = require "resty.checkups.api"
local callback = function(host, port)
local res = ngx.location.capture("/" .. port)
ngx.say(res.body)
return 1
end
local ok, err
-- connect to a dead server, no upstream available
ok, err = checkups.ready_ok("ups1", callback)
if err then ngx.say(err) end
-- add server to ups1
ok, err = checkups.update_upstream("ups1", {
{
servers = {
{host="127.0.0.1", port=12350, weight=10, max_fails=3, fail_timeout=10},
}
},
})
if err then ngx.say(err) end
ngx.sleep(1)
ok, err = checkups.ready_ok("ups1", callback)
if err then ngx.say(err) end
ok, err = checkups.ready_ok("ups1", callback)
if err then ngx.say(err) end
-- add server to new upstream
ok, err = checkups.update_upstream("ups2", {
{
servers = {
{host="127.0.0.1", port=12351},
}
},
})
if err then ngx.say(err) end
ngx.sleep(1)
ok, err = checkups.ready_ok("ups2", callback)
if err then ngx.say(err) end
-- add server to ups2, reset rr state
ok, err = checkups.update_upstream("ups2", {
{
servers = {
{host="127.0.0.1", port=12350, weight=10, max_fails=3, fail_timeout=10},
{host="127.0.0.1", port=12351, weight=10, max_fails=3, fail_timeout=10},
}
},
})
if err then ngx.say(err) end
ngx.sleep(1)
ok, err = checkups.ready_ok("ups2", callback)
if err then ngx.say(err) end
ok, err = checkups.ready_ok("ups2", callback)
if err then ngx.say(err) end
}
}
}
上面定义的/t
位置的典型输出为
no servers available
12350
12350
12351
12350
12351
配置
Lua 配置
Checkups 的配置文件是一个 lua 模块,它包含两个部分:全局部分和集群部分。
下面展示了一个 checkups 的示例配置文件:
-- config.lua
-- Here is the global part
_M = {}
_M.global = {
checkup_timer_interval = 15,
checkup_timer_overtime = 60,
default_heartbeat_enable = true,
checkup_shd_sync_enable = true,
shd_config_timer_interval = 1,
}
-- The rests parts are cluster configurations
_M.redis = {
enable = true,
typ = "redis",
timeout = 2,
read_timeout = 15,
send_timeout = 15,
protected = true,
cluster = {
{ -- level 1
try = 2,
servers = {
{ host = "192.168.0.1", port = 6379, weight=10, max_fails=3, fail_timeout=10 },
{ host = "192.168.0.2", port = 6379, weight=10, max_fails=3, fail_timeout=10 },
}
},
{ -- level 2
servers = {
{ host = "192.168.0.3", port = 6379, weight=10, max_fails=3, fail_timeout=10 },
}
},
},
}
_M.api = {
enable = false,
typ = "http",
http_opts = {
query = "GET /status HTTP/1.1\r\nHost: localhost\r\n\r\n",
statuses = {
[500] = false,
[502] = false,
[503] = false,
[504] = false,
},
},
mode = "hash",
cluster = {
dc1 = {
servers = {
{ host = "192.168.1.1", port = 1234, weight=10, max_fails=3, fail_timeout=10 },
}
},
dc2 = {
servers = {
{ host = "192.168.1.2", port = 1234, weight=10, max_fails=3, fail_timeout=10 },
}
}
}
}
_M.ups_from_nginx = {
timeout = 2,
cluster = {
{ -- level 1
upstream = "api.com",
},
{ -- level 2
upstream = "api.com",
upstream_only_backup = true,
},
},
}
return _M
全局配置
checkup_timer_interval
: 向后端服务器发送心跳的间隔。默认值为5
。checkup_timer_overtime
: 检查以使计时器键过期的间隔。在大多数情况下,您不需要更改此值。默认值为60
。default_heartbeat_enable
: Checkups 默认情况下是否会向服务器发送心跳。默认值为true
。checkup_shd_sync_enable
: 为每个工作进程创建上游同步器。如果设置为false
,动态上游将无法正常工作。默认值为true
。shd_config_timer_interval
: 从共享内存同步上游列表的间隔。默认值等于checkup_timer_interval
。ups_status_sync_enable
: 如果设置为true
,checkups 将从 checkups 同步上游状态到 Nginx 上游块。默认值为false
。ups_status_timer_interval
: 从 checkups 同步上游状态到 Nginx 上游块的间隔。
集群配置
skey
:_M.xxxxx
。xxxxx
是此集群的skey
(服务键)。enable
: 启用或禁用向服务器发送心跳。默认值为true
。typ
: 集群类型,必须是general
、redis
、mysql
、http
之一。默认值为general
。general
: 通过 TCPsock:connect
发送心跳。redis
: 通过 redisPING
发送心跳。需要lua-resty-redis模块。mysql
: 通过 mysqldb:connect
发送心跳。需要lua-resty-mysql模块。http
: 通过 HTTP 请求发送心跳。您可以在http_opts
中设置自定义的 HTTP 请求和响应代码。
timeout
: 连接到上游服务器的超时时间。默认值为5
。read_timeout
: 从上游服务器读取数据的超时时间。默认值等于timeout
。send_timeout
: 向上游服务器写入数据的超时时间。默认值等于timeout
。http_opts
: HTTP 心跳配置。仅适用于typ="http"
。query
: 用于发送心跳的 HTTP 请求。statuses
: 如果服务器返回的代码设置为false
,则认为服务器已失败。
mode
: 负载均衡模式。可以设置为hash
、url_hash
或ip_hash
。Checkups 将根据hash_key
、ngx.var.uri
或ngx.var.remote_addr
对服务器进行负载均衡。默认值为wrr
。protected
: 如果设置为true
,并且集群中的所有服务器都已失败,checkups 不会将最后一个失败的服务器标记为不可用(err
),而是将其标记为unstable
(在下一次尝试中仍然可用)。默认值为true
。cluster
: 您可以根据集群优先级配置多个层级,在每个层级上,您可以配置一个servers
集群。只有当先前层级中的所有服务器都被认为不可用时,checkups 才会尝试下一层级。
除了按层级尝试集群之外,您还可以配置 checkups 按键尝试集群(请参阅上面的api
集群)。请记住,您还应传递额外的参数(例如opts.cluster_key={"dc1", "dc2"}
或opts.cluster_key={3, 1, 2}
)到checkups.read_ok,以使 checkups 按dc1
、dc2
或level 3
、level 1
、level 2
的顺序进行尝试。如果您没有向checkups.ready_ok传递opts.cluster_key
,checkups 仍然会按层级尝试集群。对于上面的api
集群,checkups 最终会返回no servers available
。
try
: 重试次数。默认值为服务器数量。try_timeout
: 限制请求响应的时间,类似于 nginxproxy_next_upstream_timeout
。servers
:servers
的配置列出如下:weight
: 设置服务器的权重。默认值为1
。max_fails
: 设置在fail_timeout
参数设置的持续时间内,与服务器通信失败的尝试次数。默认情况下,失败尝试次数设置为0
,这将禁用尝试计数。如果typ="http"
,则通过http_opts.statuses
定义什么被视为失败尝试,或者通过checkups.ready_ok返回nil
/false
。此选项仅在轮询中可用。fail_timeout
: 设置在持续时间内,应发生与服务器通信的指定次数失败尝试以将服务器视为不可用,以及服务器被视为不可用的时间段。默认情况下,该参数设置为10
秒。此选项仅在轮询中可用。
upstream
: Nginx 上游块的名称。Checkups 将在prepare_checker中从 Nginx conf 的上游块中提取服务器。需要lua-upstream-nginx-module模块。upstream_only_backup
: 如果设置为true
,checkups 将仅从 Nginx 上游块中提取备份服务器。
Nginx 配置
将 lua 配置文件和 checkups 的路径添加到lua_package_path
中,并创建 checkups 使用的 lua 共享字典。您应该将这些行放入 Nginx 配置文件中的http
块中。
lua_package_path "/path/to/lua-resty-checkups/lib/?.lua;/path/to/config.lua;;";
lua_shared_dict state 10m;
lua_shared_dict mutex 1m;
lua_shared_dict locks 1m;
lua_shared_dict config 10m;
API
prepare_checker
语法: prepare_checker(config)
阶段: init_by_lua init_worker_by_lua
将配置从config.lua
复制到 checkups,从 Nginx 上游块中提取服务器,并进行一些基本初始化。此方法可以在init
阶段或init_worker
阶段调用。如果您想要从 Nginx 上游块中提取服务器,则必须在init_worker
阶段调用此方法。
create_checker
语法: create_checker()
阶段: init_worker_by_lua
创建心跳计时器和上游同步计时器。在所有工作进程中,只创建一个心跳计时器。强烈建议在init_worker
阶段调用此方法。
ready_ok
语法: res, err = ready_ok(skey, callback, opts?)
阶段: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*
从集群skey
中选择一个可用的peer
,并调用callback(peer.host, peer.port, opts)
。
opts
表接受以下字段:
cluster_key
: 按cluster_key
尝试集群。Checkups 将按cluster_key
的顺序尝试集群。clusters_key
可以是集群的名称或集群的层级。集群示例:{"cluster_name_A", "name_B", "name_C"}
。层级示例:{3, 2, 1}
。hash_key
: 在hash
负载均衡模式中使用的键。如果未设置,将使用ngx.req.uri
。try
: 重试次数不超过try
次。try_timeout
: 限制请求响应的时间,类似于 nginxproxy_next_upstream_timeout
。
如果成功,返回callback
的返回值,否则返回nil
和一个描述错误的字符串。
如果callback
返回nil
或false
,checkups 将认为这是一个失败的尝试,并将使用另一个 peer 重试callback
。因此,**始终记住不要在成功的回调后返回nil
或false
。**
select_peer
语法: peer, err = select_peer(skey)
上下文: rewrite_by_lua*, access_by_lua*, content_by_lua*, balancer_by_lua
从集群skey
中选择一个可用的 peer。
返回一个包含可用 peer 的host
和port
的表。
如果出现错误,将返回 nil 和一个描述错误的字符串。
get_status
语法: status = get_status()
阶段: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*
以json
格式返回 checkups 状态。
get_ups_timeout
语法: connect_timeout, send_timeout, read_timeout = get_ups_timeout(skey)
阶段: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*
返回集群skey
的超时时间。
feedback_status
语法: ok, err = feedback_status(skey, host, port, failed)
上下文: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, balancer_by_lua.*
将集群skey
中的服务器host:port
标记为失败(true
)或可用(false
)。
如果成功,返回1
,否则返回nil
和一个描述错误的字符串。
update_upstream
语法: ok, err = update_upstream(skey, upstream)
阶段: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*
更新集群skey
。upstream
与config.lua
中的cluster
格式相同。
如果成功,返回true
,否则返回false
和一个描述错误的字符串。
delete_upstream
语法: ok, err = delete_upstream(skey)
阶段: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*
从上游列表中删除集群skey
。
如果成功,返回true
,否则返回false
和一个描述错误的字符串。
版权和许可
该捆绑包本身是在 2-clause BSD 许可证下授权的。
版权所有 (c) 2016, UPYUN(又拍云) Inc.
此模块是在 BSD 许可证条款下授权的。
允许以源代码和二进制形式重新分发和使用,无论是否修改,前提是满足以下条件
重新分发的源代码必须保留上述版权声明、此条件列表以及以下免责声明。
二进制形式的重新分发必须在随分发提供的文档和/或其他材料中复制上述版权声明、此条件列表以及以下免责声明。
本软件由版权所有者和贡献者“按原样”提供,并且任何明示或暗示的担保,包括但不限于适销性和特定用途适用性的暗示担保,均被免除。在任何情况下,版权所有者或贡献者均不对任何直接的、间接的、偶然的、特殊的、示例性的或后果性的损害(包括但不限于替代商品或服务的采购;使用、数据或利润损失;或业务中断)负责,无论其因本软件的使用而产生,无论其是根据合同、严格责任或侵权(包括疏忽或其他原因)产生的,即使已被告知此类损害的可能性。
另请参阅
作者
firesnow
许可证
2bsd
版本
-
在纯 ngx_lua 中管理 Nginx 上游 2017-04-05 03:33:47
-
使用纯 ngx_lua 管理 Nginx 上游服务器 2017-03-22 17:31:29
-
使用纯 ngx_lua 管理 Nginx 上游服务器 2016-12-22 14:52:52