Would be great to have your thoughts on load balancing on the openresty as a proxy dns load-balance internal servers. Below is what I have done so far:
location / {
rewrite_by_lua_block {
local resolver = require "resty.dns.resolver"
local r, err = resolver:new {
nameservers = {{"8.8.8.8", 53}},
retrans = 3, -- 3 retransmissions on receive timeout
timeout = 1000, -- 1 sec
}
local domain = ngx.var.prefix .. ngx.var.domain .. "." .. os.getenv("CNS") --
xx.com
if not r then
ngx.log(ngx.ERR, "failed to instantiate the resolver: ", err)
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
-- dns query
local answers, err = r:query(domain)
if not answers then
ngx.log(ngx.ERR, "failed to query the DNS server: ", err)
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
if answers.errcode then
ngx.log(ngx.ERR, "dns server returned error code: ", answers.errcode, ": ", answers.errstr)
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
local http = require "resty.http"
local httpc = http.new()
local hosts = {}
-- default to http first
local scheme = 'http'
local upstream_port = 80
if ngx.var.scheme == 'https' then
scheme = 'https'
upstream_port = 443
end
function try(port)
_hosts = {}
httpc:set_timeout(300)
for i, _answer in ipairs(answers) do
local ok, err = httpc:connect(_answer["address"], port)
if ok then
_hosts[_answer["address"]] = port
end
end
-- If hosts are empty, it should try again to connect to other ports
if next(_hosts) == nil then
if port == 443 then
_hosts = try(80)
if next(_hosts) ~= nil then
scheme = 'http'
end
elseif port == 80 then
_hosts = try(443)
if next(_hosts) ~= nil then
scheme = 'https'
end
end
end
return _hosts
end
hosts = try(upstream_port)
if next(hosts) == nil then
local inspect = require "inspect"
ngx.status = 404
ngx.say("Cannot connect to following servers on port 80 or 443")
ngx.say(inspect(scheme))
ngx.say(inspect(answers))
ngx.exit(404)
end
-- set hosts & scheme for proxy_pass & upsteam load_balanced_by_lua
ngx.var.scheme_custom = scheme
ngx.ctx.hosts = hosts
}
proxy_pass $scheme_custom://internal_upsteam;
#error_page 502 500 = @error;
}