Created
January 10, 2017 00:21
-
-
Save lordnynex/cbeb6f4d2580536aa58b632b637cd7b4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
http { | |
lua_shared_dict healthchecks 1m; | |
upstream YOURAPP { | |
server 0.0.0.1; # just an invalid address as a place holder | |
balancer_by_lua_block { | |
local balancer = require "ngx.balancer" | |
-- well, usually we calculate the peer's host and port | |
-- according to some balancing policies instead of using | |
-- hard-coded values like below | |
local host = "127.0.0.2" | |
local port = 8080 | |
local ok, err = balancer.set_current_peer(host, port) | |
if not ok then | |
ngx.log(ngx.ERR, "failed to set the current peer: ", err) | |
return ngx.exit(500) | |
end | |
} | |
} | |
keepalive 10; # connection pool | |
}; | |
server { | |
init_worker_by_lua_block { | |
local hc = require "resty.upstream.healthcheck" | |
local ok, err = hc.spawn_checker{ | |
shm = "healthchecks", -- defined by "lua_shared_dict" | |
upstream = "YOURAPP", -- defined by "upstream" | |
type = "http", | |
-- get /healthcheck with a host header | |
http_req = "GET /healthcheck HTTP/1.0\r\nHost: some.host.header.if.needed.com\r\n\r\n", | |
interval = 2000, -- run the check cycle every 2 sec | |
timeout = 1000, -- 1 sec is the timeout for network operations | |
fall = 3, -- # of successive failures before turning a peer down | |
rise = 2, -- # of successive successes before turning a peer up | |
-- Adding 301 as an acceptable response code in case the route changes somehow | |
valid_statuses = {200}, -- a list valid HTTP status code (indicating a healthy upstream) | |
concurrency = 10, -- concurrency level for test requests | |
} | |
if not ok then | |
ngx.log(ngx.ERR, "failed to spawn health checker: ", err) | |
return | |
end | |
} | |
location /healthcheck { | |
default_type application/json; | |
# Determine if the upstream is healthy by having atleast 1 healthy server | |
content_by_lua_block { | |
local cjson = require("cjson") | |
-- Pcall to avoid barfing on old versions of resty | |
local ok, upstream = pcall(require, "ngx.upstream") | |
if not ok then | |
ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR | |
ngx.log(ngx.ERR, "ngx_upstream_lua module required") | |
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) | |
return | |
end | |
-- This is gonna ugly | |
-- Time is short.. do better | |
local ret = { Status = "DOWN", Data = {} } | |
local us, err = upstream.get_upstreams() | |
if not us then | |
ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR | |
ngx.say(ret) | |
ngx.log(ngx.ERR, "failed to get upstream names: " .. err) | |
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) | |
return | |
end | |
local n = #us | |
local found = false | |
local down = false | |
for i = 1, n do | |
local u = us[i] | |
if u == "YOURAPP" then | |
found = true | |
local peers, err = upstream.get_primary_peers(u) | |
if not peers then | |
ret.Error = "failed to get primary peers in upstream " .. u .. ": " .. err | |
ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR | |
ngx.say(cjson.encode(ret)) | |
ngx.log(ngx.ERR, "failed to get primary peers in upstream " .. u .. ": " .. err) | |
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) | |
return | |
end | |
ret.Data = peers | |
-- Terminate upstream loop | |
break | |
end | |
end | |
if #ret.Data == 0 then | |
ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR | |
ngx.say(cjson.encode(ret)) | |
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) | |
return | |
end | |
if ret.Data[1].down then | |
ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR | |
ngx.say(cjson.encode(ret)) | |
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) | |
return | |
else | |
ret.Status = "UP" | |
ret.Data[1].down = false | |
ngx.status = ngx.HTTP_OK | |
ngx.say(cjson.encode(ret)) | |
ngx.exit(ngx.HTTP_OK) | |
return | |
end | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment