You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by we...@apache.org on 2020/02/19 12:30:43 UTC

[incubator-apisix] branch master updated: bugfix: updated the dns parse result by TTL. (#1077)

This is an automated email from the ASF dual-hosted git repository.

wenming pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new de16a7e  bugfix: updated the dns parse result by TTL. (#1077)
de16a7e is described below

commit de16a7e04f6d316a05743666261f159508355416
Author: YuanSheng Wang <me...@gmail.com>
AuthorDate: Wed Feb 19 20:30:34 2020 +0800

    bugfix: updated the dns parse result by TTL. (#1077)
---
 bin/apisix                   |  2 +-
 conf/config.yaml             |  1 +
 lua/apisix.lua               | 59 +++++++++++++++++++++++++++++++++-----------
 lua/apisix/core/lrucache.lua |  4 ++-
 lua/apisix/core/utils.lua    | 14 +++++++++--
 t/core/lrucache.t            | 37 +++++++++++++++++++++++++++
 6 files changed, 99 insertions(+), 18 deletions(-)

diff --git a/bin/apisix b/bin/apisix
index 7e4b89a..5e68c3f 100755
--- a/bin/apisix
+++ b/bin/apisix
@@ -183,7 +183,7 @@ http {
 
     lua_socket_log_errors off;
 
-    resolver {% for _, dns_addr in ipairs(dns_resolver or {}) do %} {*dns_addr*} {% end %} ipv6=off;
+    resolver {% for _, dns_addr in ipairs(dns_resolver or {}) do %} {*dns_addr*} {% end %} valid={*dns_resolver_valid*} ipv6=off;
     resolver_timeout 5;
 
     lua_http10_buffering off;
diff --git a/conf/config.yaml b/conf/config.yaml
index 9e098d9..3281f47 100644
--- a/conf/config.yaml
+++ b/conf/config.yaml
@@ -55,6 +55,7 @@ apisix:
     - 223.5.5.5
     - 1.1.1.1
     - 8.8.8.8
+  dns_resolver_valid: 30          # valid time for dns result 30 seconds
 
   ssl:
     enable: true
diff --git a/lua/apisix.lua b/lua/apisix.lua
index bee4376..7517c46 100644
--- a/lua/apisix.lua
+++ b/lua/apisix.lua
@@ -33,9 +33,7 @@ local tostring      = tostring
 local load_balancer
 
 
-local parsed_domain = core.lrucache.new({
-    ttl = 300, count = 512
-})
+local parsed_domain
 
 
 local _M = {version = 0.3}
@@ -85,6 +83,14 @@ function _M.http_init_worker()
     end
 
     require("apisix.debug").init_worker()
+
+    local local_conf = core.config.local_conf()
+    local dns_resolver_valid = local_conf and local_conf.apisix and
+                        local_conf.apisix.dns_resolver_valid
+
+    parsed_domain = core.lrucache.new({
+        ttl = dns_resolver_valid, count = 512, invalid_stale = true,
+    })
 end
 
 
@@ -174,14 +180,20 @@ local function parse_domain_in_up(up, ver)
         local host, port = core.utils.parse_addr(addr)
         if not ipmatcher.parse_ipv4(host) and
            not ipmatcher.parse_ipv6(host) then
-            local ip_info = core.utils.dns_parse(dns_resolver, host)
-            core.log.info("parse addr: ", core.json.delay_encode(ip_info),
-                          " resolver: ", core.json.delay_encode(dns_resolver),
-                          " addr: ", addr)
-            if ip_info and ip_info.address then
+            local ip_info, err = core.utils.dns_parse(dns_resolver, host)
+            if not ip_info then
+                return nil, err
+            end
+
+            core.log.info("parse addr: ", core.json.delay_encode(ip_info))
+            core.log.info("resolver: ", core.json.delay_encode(dns_resolver))
+            core.log.info("host: ", host)
+            if ip_info.address then
                 new_nodes[ip_info.address .. ":" .. port] = weight
                 core.log.info("dns resolver domain: ", host, " to ",
                               ip_info.address)
+            else
+                return nil, "failed to parse domain in route"
             end
         else
             new_nodes[addr] = weight
@@ -206,15 +218,22 @@ local function parse_domain_in_route(route, ver)
         local host, port = core.utils.parse_addr(addr)
         if not ipmatcher.parse_ipv4(host) and
            not ipmatcher.parse_ipv6(host) then
-            local ip_info = core.utils.dns_parse(dns_resolver, host)
-            core.log.info("parse addr: ", core.json.delay_encode(ip_info),
-                          " resolver: ", core.json.delay_encode(dns_resolver),
-                          " addr: ", addr)
+            local ip_info, err = core.utils.dns_parse(dns_resolver, host)
+            if not ip_info then
+                return nil, err
+            end
+
+            core.log.info("parse addr: ", core.json.delay_encode(ip_info))
+            core.log.info("resolver: ", core.json.delay_encode(dns_resolver))
+            core.log.info("host: ", host)
             if ip_info and ip_info.address then
                 new_nodes[ip_info.address .. ":" .. port] = weight
                 core.log.info("dns resolver domain: ", host, " to ",
                               ip_info.address)
+            else
+                return nil, "failed to parse domain in route"
             end
+
         else
             new_nodes[addr] = weight
         end
@@ -312,8 +331,12 @@ function _M.http_access_phase()
         if upstreams_etcd then
             local upstream = upstreams_etcd:get(tostring(up_id))
             if upstream.has_domain then
-                parsed_domain(upstream, api_ctx.conf_version,
-                              parse_domain_in_up, upstream)
+                local _, err = parsed_domain(upstream, api_ctx.conf_version,
+                                             parse_domain_in_up, upstream)
+                if err then
+                    core.log.error("failed to parse domain in upstream: ", err)
+                    return core.response.exit(500)
+                end
             end
 
             if upstream.value.enable_websocket then
@@ -520,6 +543,14 @@ function _M.stream_init_worker()
     plugin.init_worker()
 
     load_balancer = require("apisix.balancer").run
+
+    local local_conf = core.config.local_conf()
+    local dns_resolver_valid = local_conf and local_conf.apisix and
+                        local_conf.apisix.dns_resolver_valid
+
+    parsed_domain = core.lrucache.new({
+        ttl = dns_resolver_valid, count = 512, invalid_stale = true,
+    })
 end
 
 
diff --git a/lua/apisix/core/lrucache.lua b/lua/apisix/core/lrucache.lua
index 6804673..aee4697 100644
--- a/lua/apisix/core/lrucache.lua
+++ b/lua/apisix/core/lrucache.lua
@@ -32,6 +32,7 @@ local function new_lru_fun(opts)
     local item_count = opts and opts.count or GLOBAL_ITEMS_COUNT
     local item_ttl = opts and opts.ttl or GLOBAL_TTL
     local item_release = opts and opts.release
+    local invalid_stale = opts and opts.invalid_stale
     local lru_obj = lru_new(item_count)
 
     return function (key, version, create_obj_fun, ...)
@@ -45,7 +46,8 @@ local function new_lru_fun(opts)
             return obj.val
         end
 
-        if stale_obj and stale_obj._cache_ver == version then
+        if not invalid_stale and stale_obj and
+           stale_obj._cache_ver == version then
             lru_obj:set(key, stale_obj, item_ttl)
 
             local met_tab = getmetatable(stale_obj)
diff --git a/lua/apisix/core/utils.lua b/lua/apisix/core/utils.lua
index 44a380c..98e678e 100644
--- a/lua/apisix/core/utils.lua
+++ b/lua/apisix/core/utils.lua
@@ -57,7 +57,7 @@ function _M.split_uri(uri)
 end
 
 
-function _M.dns_parse(resolvers, domain)
+local function dns_parse(resolvers, domain)
     local r, err = resolver:new{
         nameservers = table.clone(resolvers),
         retrans = 5,  -- 5 retransmissions on receive timeout
@@ -79,8 +79,18 @@ function _M.dns_parse(resolvers, domain)
     end
 
     local idx = math.random(1, #answers)
-    return answers[idx]
+    local answer = answers[idx]
+    if answer.type == 1 then
+        return answer
+    end
+
+    if answer.type ~= 5 then
+        return nil, "unsupport DNS answer"
+    end
+
+    return dns_parse(resolvers, answer.cname)
 end
+_M.dns_parse = dns_parse
 
 
 local function rfind_char(s, ch, idx)
diff --git a/t/core/lrucache.t b/t/core/lrucache.t
index bd5a32e..bfb18ee 100644
--- a/t/core/lrucache.t
+++ b/t/core/lrucache.t
@@ -204,3 +204,40 @@ release: {"_cache_ver":"t1","name":"aaa"}
 obj: {"_cache_ver":"t2","name":"bbb"}
 --- no_error_log
 [error]
+
+
+
+=== TEST 6: invalid_stale = true
+--- config
+    location /t {
+        content_by_lua_block {
+            local core = require("apisix.core")
+
+            local idx = 0
+            local function create_obj()
+                idx = idx + 1
+                return {idx = idx}
+            end
+
+            local lru_get = core.lrucache.new({
+                ttl = 0.1, count = 256, invalid_stale = true,
+            })
+
+            local obj = lru_get("key", "ver", create_obj)
+            ngx.say("obj: ", core.json.encode(obj))
+            local obj = lru_get("key", "ver", create_obj)
+            ngx.say("obj: ", core.json.encode(obj))
+
+            ngx.sleep(0.15)
+            local obj = lru_get("key", "ver", create_obj)
+            ngx.say("obj: ", core.json.encode(obj))
+        }
+    }
+--- request
+GET /t
+--- response_body
+obj: {"idx":1,"_cache_ver":"ver"}
+obj: {"idx":1,"_cache_ver":"ver"}
+obj: {"idx":2,"_cache_ver":"ver"}
+--- no_error_log
+[error]