Skip to content

Commit

Permalink
change: default to cache DNS record according to the TTL
Browse files Browse the repository at this point in the history
Since lua-resty-dns-client provides an internal cache, we don't need to
cache it twice.

Signed-off-by: spacewander <spacewanderlzx@gmail.com>
  • Loading branch information
spacewander committed Feb 5, 2021
1 parent e1dbe2c commit 769f045
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 169 deletions.
35 changes: 35 additions & 0 deletions .travis/apisix_cli_test/test_validate_config.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env bash

#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# validate the config.yaml

. ./.travis/apisix_cli_test/common.sh

echo '
apisix:
dns_resolver_valid: "/apisix"
' > conf/config.yaml

out=$(make init 2>&1 || true)
if ! echo "$out" | grep 'dns_resolver_valid should be a number'; then
echo "failed: dns_resolver_valid should be a number"
exit 1
fi

echo "passed: dns_resolver_valid should be a number"
4 changes: 2 additions & 2 deletions apisix/cli/ngx_tpl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ stream {
lua_shared_dict lrucache-lock-stream 10m;
resolver {% for _, dns_addr in ipairs(dns_resolver or {}) do %} {*dns_addr*} {% end %} valid={*dns_resolver_valid*};
resolver {% for _, dns_addr in ipairs(dns_resolver or {}) do %} {*dns_addr*} {% end %} {% if dns_resolver_valid then %}valid={*dns_resolver_valid*}{% end %};
resolver_timeout {*resolver_timeout*};
# stream configuration snippet starts
Expand Down Expand Up @@ -187,7 +187,7 @@ http {
lua_socket_log_errors off;
resolver {% for _, dns_addr in ipairs(dns_resolver or {}) do %} {*dns_addr*} {% end %} valid={*dns_resolver_valid*};
resolver {% for _, dns_addr in ipairs(dns_resolver or {}) do %} {*dns_addr*} {% end %} {% if dns_resolver_valid then %}valid={*dns_resolver_valid*}{% end %};
resolver_timeout {*resolver_timeout*};
lua_http10_buffering off;
Expand Down
6 changes: 6 additions & 0 deletions apisix/cli/ops.lua
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,12 @@ Please modify "admin_key" in conf/config.yaml .
end
end

if yaml_conf.apisix.dns_resolver_valid then
if tonumber(yaml_conf.apisix.dns_resolver_valid) == nil then
util.die("apisix->dns_resolver_valid should be a number")
end
end

-- Using template.render
local sys_conf = {
use_or_1_15 = use_or_1_15,
Expand Down
6 changes: 6 additions & 0 deletions apisix/core/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
local config_local = require("apisix.core.config_local")
local core_str = require("apisix.core.string")
local table = require("apisix.core.table")
local json = require("apisix.core.json")
Expand Down Expand Up @@ -85,11 +86,16 @@ end

local function dns_parse(domain)
if dns_resolvers ~= current_inited_resolvers then
local local_conf = config_local.local_conf()
local valid = table.try_read_attr(local_conf, "apisix", "dns_resolver_valid")

local opts = {
ipv6 = true,
nameservers = table.clone(dns_resolvers),
retrans = 5, -- 5 retransmissions on receive timeout
timeout = 2000, -- 2 sec
order = {"last", "A", "AAAA", "CNAME"}, -- avoid querying SRV (we don't support it yet)
validTtl = valid,
}
local ok, err = dns_client.init(opts)
if not ok then
Expand Down
26 changes: 2 additions & 24 deletions apisix/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ end
local load_balancer
local local_conf
local dns_resolver
local lru_resolved_domain
local ver_header = "APISIX/" .. core.version.VERSION


Expand Down Expand Up @@ -121,12 +120,6 @@ function _M.http_init_worker()
require("apisix.upstream").init_worker()

local_conf = core.config.local_conf()
local dns_resolver_valid = local_conf and local_conf.apisix and
local_conf.apisix.dns_resolver_valid

lru_resolved_domain = core.lrucache.new({
ttl = dns_resolver_valid, count = 512, invalid_stale = true,
})

if local_conf.apisix and local_conf.apisix.enable_server_tokens == false then
ver_header = "APISIX"
Expand Down Expand Up @@ -420,16 +413,8 @@ function _M.http_access_phase()
end

if upstream.has_domain then
-- try to fetch the resolved domain, if we got `nil`,
-- it means we need to create the cache by handle.
-- the `api_ctx.conf_version` is different after we called
-- `parse_domain_in_up`, need to recreate the cache by new
-- `api_ctx.conf_version`
local err
upstream, err = lru_resolved_domain(upstream,
upstream.modifiedIndex,
parse_domain_in_up,
upstream)
upstream, err = parse_domain_in_up(upstream)
if err then
core.log.error("failed to get resolved upstream: ", err)
return core.response.exit(500)
Expand All @@ -454,8 +439,7 @@ function _M.http_access_phase()
else
if route.has_domain then
local err
route, err = lru_resolved_domain(route, api_ctx.conf_version,
parse_domain_in_route, route)
route, err = parse_domain_in_route(route)
if err then
core.log.error("failed to get resolved route: ", err)
return core.response.exit(500)
Expand Down Expand Up @@ -806,12 +790,6 @@ function _M.stream_init_worker()
load_balancer = require("apisix.balancer").run

local_conf = core.config.local_conf()
local dns_resolver_valid = local_conf and local_conf.apisix and
local_conf.apisix.dns_resolver_valid

lru_resolved_domain = core.lrucache.new({
ttl = dns_resolver_valid, count = 512, invalid_stale = true,
})
end


Expand Down
2 changes: 1 addition & 1 deletion conf/config-default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ apisix:
# dns_resolver: # If not set, read from `/etc/resolv.conf`
# - 1.1.1.1
# - 8.8.8.8
dns_resolver_valid: 30 # valid time for dns result 30 seconds
# dns_resolver_valid: 30 # if given, override the TTL of the valid records. The unit is second.
resolver_timeout: 5 # resolver timeout
ssl:
enable: true
Expand Down
3 changes: 3 additions & 0 deletions t/coredns/db.test.local
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ $ORIGIN test.local.
3600 IN NS b.iana-servers.net.

ipv6 IN AAAA ::1

ttl 300 IN A 127.0.0.1
ttl.1s 1 IN A 127.0.0.1
162 changes: 162 additions & 0 deletions t/node/upstream-domain-with-special-dns.t
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,165 @@ upstreams:
GET /hello
--- response_body
hello world
=== TEST 2: default ttl
--- log_level: debug
--- apisix_yaml
upstreams:
-
id: 1
nodes:
ttl.test.local:1980: 1
type: roundrobin
--- config
location /t {
content_by_lua_block {
local http = require "resty.http"
local uri = "http://127.0.0.1:" .. ngx.var.server_port .. "/hello"
for i = 1, 3 do
local httpc = http.new()
local res, err = httpc:request_uri(uri, {method = "GET"})
if not res or res.body ~= "hello world\n" then
ngx.say(err)
return
end
end
}
}
--- request
GET /t
--- error_log
"ttl":300
--- grep_error_log eval
qr/connect to 127.0.0.1:1053/
--- grep_error_log_out
connect to 127.0.0.1:1053
=== TEST 3: override ttl
--- log_level: debug
--- yaml_config
apisix:
node_listen: 1984
config_center: yaml
enable_admin: false
dns_resolver_valid: 900
--- apisix_yaml
upstreams:
-
id: 1
nodes:
ttl.test.local:1980: 1
type: roundrobin
--- config
location /t {
content_by_lua_block {
local http = require "resty.http"
local uri = "http://127.0.0.1:" .. ngx.var.server_port .. "/hello"
for i = 1, 3 do
local httpc = http.new()
local res, err = httpc:request_uri(uri, {method = "GET"})
if not res or res.body ~= "hello world\n" then
ngx.say(err)
return
end
end
}
}
--- request
GET /t
--- grep_error_log eval
qr/connect to 127.0.0.1:1053/
--- grep_error_log_out
connect to 127.0.0.1:1053
--- error_log
"ttl":900
=== TEST 4: cache expire
--- log_level: debug
--- apisix_yaml
upstreams:
-
id: 1
nodes:
ttl.1s.test.local:1980: 1
type: roundrobin
--- config
location /t {
content_by_lua_block {
local http = require "resty.http"
local uri = "http://127.0.0.1:" .. ngx.var.server_port .. "/hello"
for i = 1, 2 do
for j = 1, 3 do
local httpc = http.new()
local res, err = httpc:request_uri(uri, {method = "GET"})
if not res or res.body ~= "hello world\n" then
ngx.say(err)
return
end
end
if i < 2 then
ngx.sleep(1.1)
end
end
}
}
--- request
GET /t
--- grep_error_log eval
qr/connect to 127.0.0.1:1053/
--- grep_error_log_out
connect to 127.0.0.1:1053
connect to 127.0.0.1:1053
=== TEST 5: cache expire (override ttl)
--- log_level: debug
--- yaml_config
apisix:
node_listen: 1984
config_center: yaml
enable_admin: false
dns_resolver_valid: 1
--- apisix_yaml
upstreams:
-
id: 1
nodes:
ttl.test.local:1980: 1
type: roundrobin
--- config
location /t {
content_by_lua_block {
local http = require "resty.http"
local uri = "http://127.0.0.1:" .. ngx.var.server_port .. "/hello"
for i = 1, 2 do
for j = 1, 3 do
local httpc = http.new()
local res, err = httpc:request_uri(uri, {method = "GET"})
if not res or res.body ~= "hello world\n" then
ngx.say(err)
return
end
end
if i < 2 then
ngx.sleep(1.1)
end
end
}
}
--- request
GET /t
--- grep_error_log eval
qr/connect to 127.0.0.1:1053/
--- grep_error_log_out
connect to 127.0.0.1:1053
connect to 127.0.0.1:1053
Loading

0 comments on commit 769f045

Please sign in to comment.