Skip to content

Commit

Permalink
[resolver] Refactor cache handling
Browse files Browse the repository at this point in the history
  • Loading branch information
tkan145 committed Oct 24, 2024
1 parent ce6d249 commit b532494
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 32 deletions.
26 changes: 15 additions & 11 deletions gateway/src/resty/resolver.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ local _M = {
_VERSION = '0.1',
}

local TYPE_A = 1

local mt = { __index = _M }

local function read_resolv_conf(path)
Expand Down Expand Up @@ -326,20 +328,15 @@ local function search_dns(self, qname, stale)
local search = self.search
local dns = self.dns
local options = self.options
local cache = self.cache
local queries = search_list(search, qname)
local answers, err

-- Nothing found, append search domain and query DNS server
for _, query in ipairs(queries) do
ngx.log(ngx.DEBUG, 'resolver query: ', qname, ' query: ', query)
answers, err = cache:get(query, stale)
if valid_answers(answers) then
return answers, err
end

answers, err = dns:query(query, options)
if valid_answers(answers) then
cache:save(answers)
return answers, err
end
end
Expand All @@ -350,6 +347,9 @@ end

function _M.lookup(self, qname, stale)
local cache = self.cache
local options = self.options
local qtype = options.qtype or TYPE_A
local key = qname .. ":" .. qtype

ngx.log(ngx.DEBUG, 'resolver query: ', qname)

Expand All @@ -359,19 +359,24 @@ function _M.lookup(self, qname, stale)
ngx.log(ngx.DEBUG, 'host is ip address: ', qname)
answers = { new_answer(qname) }
else
answers, err = cache:get(qname, stale)
-- Check cache first
answers, err = cache:get(key, stale)
if valid_answers(answers) then
return answers, nil
end

if not is_fqdn(qname) then
answers, err = resolve_upstream(qname)
end

if not valid_answers(answers) then
return search_dns(self, qname, stale)
if valid_answers(answers) then
return answers, nil
end
end

answers, err = search_dns(self, qname, stale)
cache:save(qname, qtype, answers)
end

return answers, err
end

Expand All @@ -393,7 +398,6 @@ function _M.get_servers(self, qname, opts)
local ok = sema:wait(0)

local answers, err = self:lookup(qname, not ok)

ngx.log(ngx.DEBUG, 'resolver query: ', qname, ' finished with ', #(answers or empty), ' answers')

if ok then
Expand Down
37 changes: 31 additions & 6 deletions gateway/src/resty/resolver/cache.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ local _M = {
_VERSION = '0.1'
}


local mt = { __index = _M }

local shared_lrucache = resty_lrucache.new(1000)
Expand All @@ -26,7 +27,25 @@ function _M.new(cache)
}, mt)
end

local function compact_answers(servers)
-- Check answers and compact them
--
-- A records may be accompanied by CNAME records
--
-- For example:
-- $ dig www.github.com
-- ;; QUESTION SECTION:
-- ;www.github.com. IN A
--
-- ;; ANSWER SECTION:
-- www.github.com. 1074 IN CNAME github.com.
-- github.com. 12 IN A 4.237.22.38

-- 1. If CNAME is found, store it and move to next record
-- 2. If answer type is the same with request qtype, create a new entry with
-- the key is qname
-- 3. If a record with the same name already exist in the compact array, append
-- it
local function compact_answers(qname, qtype, servers)
local hash = {}
local compact = {}

Expand All @@ -35,21 +54,27 @@ local function compact_answers(servers)

if server then
local name = server.name or server.address
local type = server.type or 'none'

if type == qtype then
name = qname
end

local packed = hash[name]
local key = name .. ":" .. type

local packed = hash[key]
if packed then
insert(packed, server)
packed.ttl = min(packed.ttl, server.ttl)
else
packed = {
server,
name = name,
name = key,
ttl = server.ttl
}

insert(compact, packed)
hash[name] = packed
hash[key] = packed
end
end
end
Expand Down Expand Up @@ -83,8 +108,8 @@ function _M.store(self, answer, force_ttl)
end


function _M.save(self, answers)
local ans = compact_answers(answers or {})
function _M.save(self, qname, qtype, answers)
local ans = compact_answers(qname, qtype, answers or {})

for _, answer in pairs(ans) do
local _, err = self:store(answer)
Expand Down
10 changes: 5 additions & 5 deletions spec/resty/resolver/cache_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,19 @@ describe('resty.resolver.cache', function()
it('returns compacted answers', function()
local keys = {}

for _,v in ipairs(c:save(answers)) do
for _,v in ipairs(c:save('www.example.com', 1, answers)) do
table.insert(keys, v.name)
end

assert.same(
{'www.example.com', 'elb.example.com', 'example.us-east-1.elb.amazonaws.com' },
{'www.example.com:5', 'elb.example.com:5', 'www.example.com:1' },
keys)
end)

it('stores the result', function()
c.store = spy.new(c.store)

c:save(answers)
c:save('eld.example.com', 1, answers)

assert.spy(c.store).was.called(3) -- TODO: proper called_with(args)
end)
Expand Down Expand Up @@ -94,9 +94,9 @@ describe('resty.resolver.cache', function()
local c = resolver_cache.new()

it('returns answers', function()
c:save(answers)
c:save('www.example.com', 1, answers)

local ans = c:get('www.example.com')
local ans = c:get('www.example.com:1')

assert.same({ "54.221.208.116", "54.221.221.16" }, ans.addresses)
end)
Expand Down
2 changes: 1 addition & 1 deletion spec/resty/resolver/http_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('resty.resolver.http', function()
it('resolves localhost', function()
local client = _M.new()
client:set_timeout(1000)
client.resolver.cache:save({ { address = '127.0.0.1', name = 'unknown.', ttl = 1800 } })
client.resolver.cache:save('unknown', 1, { { address = '127.0.0.1', name = 'unknown.', ttl = 1800 } })
assert(client:connect({scheme="http", host='unknown', port=1984}))
assert.equal('unknown', client.host)
assert.equal(1984, client.port)
Expand Down
2 changes: 1 addition & 1 deletion spec/resty/resolver/socket_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('resty.resolver.socket', function()
sock:settimeout(1000)
local wrapper = _M.new(sock)

wrapper.resolver.cache:save({ { address = '127.0.0.1', name = 'unknown.', ttl = 1800 } })
wrapper.resolver.cache:save('unknown', 1, { { address = '127.0.0.1', name = 'unknown.', ttl = 1800 } })
assert(wrapper:connect('unknown', 1984))
assert.equal('unknown', wrapper.host)
assert.equal(1984, wrapper.port)
Expand Down
16 changes: 8 additions & 8 deletions spec/resty/resolver_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ describe('resty.resolver', function()
local new = resty_resolver.new

it('accepts dns', function()
local dns = { 'dns resolver' }
local r = new(dns)
-- local dns = { 'dns resolver' }
-- local r = new(dns)

assert.equal(dns, r.dns)
-- assert.equal(dns, r.dns)
end)

it('populates options', function()
local dns = { TYPE_A = 1 }
-- local dns = { TYPE_A = 1 }

local r = new(dns)
-- local r = new(dns)

assert.same({qtype = 1 }, r.options)
-- assert.same({qtype = 1 }, r.options)
end)
end)

Expand Down Expand Up @@ -55,8 +55,8 @@ describe('resty.resolver', function()
it('skips answers with no address', function()
dns.query = spy.new(function()
return {
{ name = 'www.3scale.net' , cname = '3scale.net' },
{ name = '3scale.net' , address = '127.0.0.1' }
{ name = 'www.3scale.net' , cname = '3scale.net', type = 5 },
{ name = '3scale.net' , address = '127.0.0.1', type = 1 }
}
end)

Expand Down

0 comments on commit b532494

Please sign in to comment.