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