how to achieve nginx upstream connection pool

16 views
Skip to first unread message

Satish Kumar Andey

unread,
May 8, 2023, 12:58:32 AMMay 8
to openresty-en

We are developing an nginx openresty app that will have a high load upstream traffic. ex - https://upstream.com
However, are spending around 100 ms every time we connect to upstream.
To leverage the connection pool, I started using
http://nginx.org/en/docs/http/ngx_http_upstream_module.html with the keep alive directive.
in this directive, we have tried to make the server name dynamic using the balancer by lua block.
https://github.com/openresty/lua-nginx-module#balancer_by_lua_block
and using https://github.com/openresty/lua-resty-dns#tcp_query for dns resolution.

Though these things work for me, I am trying to find out if there is any way we can achieve DNS resolution on openresty + nginx opensource and still avoid the hard coupling of not entering the host DNS directly in the upstream block.
Because if we explicitly mention the server DNS for upstream then the nginx+openresty app fails to start when it can't resolve the DNS.

Sample code:

upstream upstream1 {
server 127.0.0.1 fail_timeout=10;
balancer_by_lua_block {
local balancer = require "ngx.balancer"
local host, port = ngx.var.upstream:match( "([^://]+):(%d+)" )
if(host == nil) then
host = string.gsub(ngx.var.upstream, "https://", "")
end;
local targetIp = upstreamSvcHostIpMap[host]
local port = upstreamSvcHostPortsMap[host]
local ok, err = balancer.set_current_peer(targetIp, port)
if not ok then
ngx.log(ngx.ERR, "failed to set the current peer: ", err)
return ngx.exit(500)
end
}
keepalive 20;
keepalive_timeout 60s;
keepalive_time 1h;
}

### DNS query

local resolver = require "resty.dns.resolver"
local _M = {}

function _M.getIpFromDNS(host)
local nameServerIp = "8.8.8.8"
if(nameServer ~= nil) then nameServerIp = nameServer; end
ngx.log(ngx.ERR, "nameServerIp: ", nameServerIp)
local r, err = resolver:new{nameservers = { nameServerIp}}
if not r then
ngx.log(ngx.ERR, "failed to instantiate the resolver: ", err)
return
end

local ans, err = r:tcp_query(host, { qtype = r.TYPE_A })
if not ans then
ngx.log(ngx.ERR, "failed to query: ", err)
return
end
for i, ans1 in ipairs(ans) do
ngx.log(ngx.ERR, ans1.name, " ", ans1.address or ans1.cname," type:", ans1.type, " class:", ans1.class," ttl:", ans1.ttl)
return ans1.address or ans1.cname
end
return nil
end

function _M.readNameServer()
local nameServerLocal = nil
local fp = assert(io.open("/etc/resolv.conf"))
for line in fp:lines() do
if line.find(line, "nameserver") then
nameServerLocal = line:match(" (.*)")
end
end
fp:close()
ngx.log(ngx.ERR, "nameServerLocal:", nameServerLocal)
return nameServerLocal
end


Any help in this regard will be appreciated.

Jun Ouyang

unread,
May 8, 2023, 3:02:13 AMMay 8
to openre...@googlegroups.com
Nope, Open source Nginx can not dynamically resolve DNS name in upstream runtime. This is the hard-core limitation at this moment.  Luckily, nginx actually does some port upstream dynamic DNS name feature to nginx open source  https://mailman.nginx.org/pipermail/nginx-devel/2023-February/4MCLSVRK7EX6DNKHFZN6CA4SKZUSA3GA.html

Satish Kumar Andey <satish...@gmail.com> 于2023年5月8日周一 12:58写道:
--
You received this message because you are subscribed to the Google Groups "openresty-en" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openresty-en...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/openresty-en/b1b824e9-5fc6-45b4-a5bb-51831066d652n%40googlegroups.com.


--
GPG public key: 4A6D297E6F74638E4D5F8E99152AC7B5F7608B26
Thanks,
Jun Ouyang
Reply all
Reply to author
Forward
0 new messages