Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change: default to cache DNS record according to the TTL #3530

Merged
merged 1 commit into from
Feb 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use JSON Schema to check configuration values?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems that the whole config.yaml doesn't have the json schema.

Copy link
Member

@membphis membphis Feb 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is time to do it in this way now

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's more proper to do it in another PR.

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