Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: health check supports custom host port. #1914

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions apisix/balancer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,10 @@ local function fetch_health_nodes(upstream, checker)
end

local host = upstream.checks and upstream.checks.active and upstream.checks.active.host
local port = upstream.checks and upstream.checks.active and upstream.checks.active.port
local up_nodes = core.table.new(0, #nodes)
for _, node in ipairs(nodes) do
local ok = checker:get_target_status(node.host, node.port, host)
local ok = checker:get_target_status(node.host, port or node.port, host)
if ok then
-- TODO filter with metadata
up_nodes[node.host .. ":" .. node.port] = node.weight
Expand Down Expand Up @@ -93,11 +94,12 @@ local function create_checker(upstream, healthcheck_parent)
})

local host = upstream.checks and upstream.checks.active and upstream.checks.active.host
local port = upstream.checks and upstream.checks.active and upstream.checks.active.port
for _, node in ipairs(upstream.nodes) do
local ok, err = checker:add_target(node.host, node.port, host)
local ok, err = checker:add_target(node.host, port or node.port, host)
if not ok then
core.log.error("failed to add new health check target: ", node.host, ":", node.port,
" err: ", err)
core.log.error("failed to add new health check target: ", node.host, ":",
port or node.port, " err: ", err)
end
end

Expand Down Expand Up @@ -195,14 +197,15 @@ local function pick_server(route, ctx)
if checker and ctx.balancer_try_count > 1 then
local state, code = get_last_failure()
local host = up_conf.checks and up_conf.checks.active and up_conf.checks.active.host
local port = up_conf.checks and up_conf.checks.active and up_conf.checks.active.port
if state == "failed" then
if code == 504 then
checker:report_timeout(ctx.balancer_ip, ctx.balancer_port, host)
checker:report_timeout(ctx.balancer_ip, port or ctx.balancer_port, host)
else
checker:report_tcp_failure(ctx.balancer_ip, ctx.balancer_port, host)
checker:report_tcp_failure(ctx.balancer_ip, port or ctx.balancer_port, host)
end
else
checker:report_http_status(ctx.balancer_ip, ctx.balancer_port, host, code)
checker:report_http_status(ctx.balancer_ip, port or ctx.balancer_port, host, code)
end
end

Expand Down
5 changes: 5 additions & 0 deletions apisix/schema_def.lua
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ local health_checker = {
timeout = {type = "number", default = 1},
concurrency = {type = "integer", default = 10},
host = host_def,
port = {
type = "integer",
minimum = 1,
maximum = 65535
},
http_path = {type = "string", default = "/"},
https_verify_certificate = {type = "boolean", default = true},
healthy = {
Expand Down
1 change: 1 addition & 0 deletions doc/health-check.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ contains: `active` or `passive`.

* `active.http_path`: The HTTP GET request path used to detect if the upstream is healthy.
* `active.host`: The HTTP request host used to detect if the upstream is healthy.
* `active.port`: The customize health check host port (optional), this will override the port in the `upstream` node.

The threshold fields of `healthy` are:
* `active.healthy.interval`: Interval between health checks for healthy targets (in seconds), the minimum is 1.
Expand Down
1 change: 1 addition & 0 deletions doc/zh-cn/health-check.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f13

* `active.http_path`: 用于发现upstream节点健康可用的HTTP GET请求路径。
* `active.host`: 用于发现upstream节点健康可用的HTTP请求主机名。
* `active.port`: 用于发现upstream节点健康可用的自定义主机端口(可选),配置此项会覆盖 `upstream` 节点中的端口。

`healthy`的阀值字段:
* `active.healthy.interval`: 健康的目标节点的健康检查间隔时间(以秒为单位),最小值为1。
Expand Down
172 changes: 172 additions & 0 deletions t/node/healthcheck.t
Original file line number Diff line number Diff line change
Expand Up @@ -621,3 +621,175 @@ GET /t
qr/^.*?\[warn\].*/
--- grep_error_log_out eval
qr/unhealthy TCP increment.*foo.com/



=== TEST 14: add route (test health check customized `port`)
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"uri": "/server_port",
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1,
"127.0.0.1:1981": 1
},
"checks": {
"active": {
"http_path": "/status",
"port": 1988,
"host": "foo.com",
"healthy": {
"interval": 1,
"successes": 1
},
"unhealthy": {
"interval": 1,
"http_failures": 2
}
}
}
}
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed



=== TEST 15: test health check customized `port`
--- config
location /t {
content_by_lua_block {
local http = require "resty.http"
local uri = "http://127.0.0.1:" .. ngx.var.server_port
.. "/server_port"

local httpc = http.new()
local res, err = httpc:request_uri(uri, {method = "GET", keepalive = false})

ngx.sleep(2)

ngx.say(res.status)
}
}
--- request
GET /t
--- response_body
200
--- grep_error_log eval
qr/^.*?\[warn\].*/
--- grep_error_log_out eval
qr/unhealthy TCP increment.*foo.com.*127.0.0.1:1988/



=== TEST 16: add route (test health check customized `port` out of minimum range)
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"uri": "/server_port",
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1,
"127.0.0.1:1981": 1
},
"checks": {
"active": {
"http_path": "/status",
"port": 0,
"host": "foo.com",
"healthy": {
"interval": 1,
"successes": 1
},
"unhealthy": {
"interval": 1,
"http_failures": 2
}
}
}
}
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body_like eval
qr/expected 0 to be greater than 1/
--- error_code chomp
400



=== TEST 17: add route (test health check customized `port` out of maximum range)
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"uri": "/server_port",
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1,
"127.0.0.1:1981": 1
},
"checks": {
"active": {
"http_path": "/status",
"port": 65536,
"host": "foo.com",
"healthy": {
"interval": 1,
"successes": 1
},
"unhealthy": {
"interval": 1,
"http_failures": 2
}
}
}
}
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body_like eval
qr/expected 65536 to be smaller than 65535/
--- error_code chomp
400