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

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


The following commit(s) were added to refs/heads/master by this push:
     new eb1af76f8 fix: avoid 503 error after dns service temporary fail 
(#13137)
eb1af76f8 is described below

commit eb1af76f83720ba92eeebe9c91e63292dbcd9ae0
Author: Rafael Rivero GarcĂ­a <[email protected]>
AuthorDate: Thu Jun 11 13:52:39 2026 +0200

    fix: avoid 503 error after dns service temporary fail (#13137)
---
 apisix/utils/upstream.lua  |  10 +++-
 t/node/upstream-node-dns.t | 131 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 140 insertions(+), 1 deletion(-)

diff --git a/apisix/utils/upstream.lua b/apisix/utils/upstream.lua
index 77f8c4d54..ece23776b 100644
--- a/apisix/utils/upstream.lua
+++ b/apisix/utils/upstream.lua
@@ -55,7 +55,15 @@ local function compare_upstream_node(up_conf, new_t)
         -- if original_nodes is set, it means that the upstream nodes
         -- are changed by `fill_node_info`, so we need to compare the new 
nodes with the
         -- original nodes.
-        old_t = up_conf.original_nodes
+        -- There is a catch, though: when service discovery or DNS resolution
+        -- fail to resolve an upstream, `nodes` is cleared but `fill_node_info`
+        -- is never called, so `original_nodes` is not updated.
+        -- Therefore `original_nodes` should only be considered valid if 
`nodes`
+        -- is not empty.
+        -- See https://github.com/apache/apisix/issues/12973
+        if #up_conf.nodes > 0 then
+            old_t = up_conf.original_nodes
+        end
     end
 
     if #new_t ~= #old_t then
diff --git a/t/node/upstream-node-dns.t b/t/node/upstream-node-dns.t
index b8dbb0bce..e09eb89db 100644
--- a/t/node/upstream-node-dns.t
+++ b/t/node/upstream-node-dns.t
@@ -556,3 +556,134 @@ GET /t
 --- grep_error_log eval
 qr/parse route which contain domain: .+("dns_value":.+){3}/
 --- grep_error_log_out
+
+
+
+=== TEST 17: upstream recovers after DNS failure when DNS returns to the same 
IP
+--- init_by_lua_block
+    require "resty.core"
+    apisix = require("apisix")
+    core = require("apisix.core")
+    apisix.http_init()
+--- config
+location /t {
+    content_by_lua_block {
+        local t = require("lib.test_admin").test
+        local code, body = t('/apisix/admin/upstreams/1',
+             ngx.HTTP_PUT,
+             [[{
+                "nodes": {
+                    "test1.com:1980": 1
+                },
+                "type": "roundrobin",
+                "desc": "new upstream"
+            }]]
+            )
+        if code >= 300 then
+            ngx.status = code
+            ngx.say(body)
+            return
+        end
+
+        code, body = t('/apisix/admin/routes/1',
+             ngx.HTTP_PUT,
+             [[{
+                    "uri": "/hello",
+                    "upstream_id": "1"
+            }]]
+            )
+        if code >= 300 then
+            ngx.status = code
+            ngx.say(body)
+            return
+        end
+
+        local utils = require("apisix.core.utils")
+        local original_dns_parse = utils.dns_parse
+        local count = 0
+        utils.dns_parse = function (domain)
+            if domain == "test1.com" then
+                count = count + 1
+                if count == 1 or count == 3 then
+                    return {address = "127.0.0.1"}
+                end
+
+                return nil, "dns server error: 3 name error"
+            end
+
+            error("unknown domain: " .. domain)
+        end
+
+        local code1 = t('/hello', ngx.HTTP_GET)
+        local code2 = t('/hello', ngx.HTTP_GET)
+        local code3 = t('/hello', ngx.HTTP_GET)
+        utils.dns_parse = original_dns_parse
+        core.log.warn("codes: ", code1, ",", code2, ",", code3)
+        ngx.say(code1, ",", code2, ",", code3)
+    }
+}
+--- request
+GET /t
+--- response_body
+200,503,200
+--- ignore_error_log
+
+
+
+=== TEST 18: route recovers after DNS failure when DNS returns to the same IP
+--- init_by_lua_block
+    require "resty.core"
+    apisix = require("apisix")
+    core = require("apisix.core")
+    apisix.http_init()
+--- config
+location /t {
+    content_by_lua_block {
+        local t = require("lib.test_admin").test
+        local code, body = t('/apisix/admin/routes/1',
+            ngx.HTTP_PUT,
+            [[{
+                "upstream": {
+                    "nodes": {
+                        "test1.com:1980": 1
+                    },
+                    "type": "roundrobin"
+                },
+                "uri": "/hello"
+            }]]
+            )
+        if code >= 300 then
+            ngx.status = code
+            ngx.say(body)
+            return
+        end
+
+        local utils = require("apisix.core.utils")
+        local original_dns_parse = utils.dns_parse
+        local count = 0
+        utils.dns_parse = function (domain)
+            if domain == "test1.com" then
+                count = count + 1
+                if count == 1 or count == 3 then
+                    return {address = "127.0.0.1"}
+                end
+
+                return nil, "dns server error: 3 name error"
+            end
+
+            error("unknown domain: " .. domain)
+        end
+
+        local code1 = t('/hello', ngx.HTTP_GET)
+        local code2 = t('/hello', ngx.HTTP_GET)
+        local code3 = t('/hello', ngx.HTTP_GET)
+        utils.dns_parse = original_dns_parse
+        core.log.warn("codes: ", code1, ",", code2, ",", code3)
+        ngx.say(code1, ",", code2, ",", code3)
+    }
+}
+--- request
+GET /t
+--- response_body
+200,503,200
+--- ignore_error_log

Reply via email to