Skip to content

bug: checker leak for domain nodes? #8932

Description

@kingluo

Current Behavior

If the route contains upstream (inline or referenced upstream) nodes in domain name form, then when overriding the route, the old checker upon the upstream is not removed. But upstream which contains nodes all in IP form has no issue.

The bug is due to DNS parsed upstream changing its parent to a temporary route copy but not the original one from etcd. So when etcd watches new changes and fails to remove the associated checker.

route.dns_value = core.table.deepcopy(route).value

Expected Behavior

The old checker should be removed.

Error Logs

No response

Steps to Reproduce

curl http://127.0.0.1:9180/apisix/admin/routes/1 \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{
    "uri":"/get",
    "upstream":{
        "nodes":[
            {
                "host":"httpbin.org",
                "port":80,
                "weight":1
            },
            {
                "host":"postman-echo.com",
                "port":80,
                "weight":1
            }
        ],
        "type":"roundrobin",
        "checks":{
            "active":{
                "concurrency":10,
                "healthy":{
                    "http_statuses":[
                        200,
                        302
                    ],
                    "interval":1,
                    "successes":2
                },
                "http_path":"/get",
                "timeout":1,
                "type":"http",
                "unhealthy":{
                    "http_failures":5,
                    "http_statuses":[
                        429,
                        404,
                        500,
                        501,
                        502,
                        503,
                        504,
                        505
                    ],
                    "interval":1,
                    "tcp_failures":2,
                    "timeouts":3
                }
            }
        }
    }
}'

# trigger checker
curl http://127.0.0.1:9080/get -X GET

# override the route
# which should remove the above checker
curl http://127.0.0.1:9180/apisix/admin/routes/1 \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{
    "uri":"/get",
    "upstream":{
        "nodes":[
            {
                "host":"httpbin.org",
                "port":80,
                "weight":1
            },
            {
                "host":"postman-echo.com",
                "port":80,
                "weight":1
            }
        ],
        "type":"roundrobin",
        "checks":{
            "active":{
                "concurrency":10,
                "healthy":{
                    "http_statuses":[
                        200,
                        302
                    ],
                    "interval":1,
                    "successes":2
                },
                "http_path":"/get",
                "timeout":1,
                "type":"http",
                "unhealthy":{
                    "http_failures":5,
                    "http_statuses":[
                        429,
                        404,
                        500,
                        501,
                        502,
                        503,
                        504,
                        505
                    ],
                    "interval":1,
                    "tcp_failures":2,
                    "timeouts":3
                }
            }
        }
    }
}'

# But checker still running
# logs

2023/02/24 14:49:42 [warn] 2384862#2384862: *65399 [lua] healthcheck.lua:1150: log(): [healthcheck] (upstream#/apisix/upstreams/1) unhealthy TIMEOUT increment (1/3) for '(52.1.93.201:80)', context: ngx.timer, client: 127.0.0.1, server: 0.0.0.0:9080
2023/02/24 14:49:42 [warn] 2384862#2384862: *65446 [lua] healthcheck.lua:1150: log(): [healthcheck] (upstream#/apisix/upstreams/1) healthy SUCCESS increment (1/2) for '(52.1.93.201:80)', context: ngx.timer, client: 127.0.0.1, server: 0.0.0.0:9080
2023/02/24 14:49:44 [warn] 2384862#2384862: *65479 [lua] healthcheck.lua:1150: log(): [healthcheck] (upstream#/apisix/upstreams/1) healthy SUCCESS increment (2/2) for '(52.1.93.201:80)', context: ngx.timer, client: 127.0.0.1, server: 0.0.0.0:9080

Use inspect plugin to check if checker is removed:

dbg.set_hook("healthcheck.lua", 434, nil, function(info)
    core.log.warn(debug.traceback("clear traceback", 3))
    return false
end)

For domain upstream, the breakpoint is not triggered.

But for IP upstreams, it's triggered.

curl http://127.0.0.1:9180/apisix/admin/routes/1 \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{
    "uri":"/get",
    "upstream":{
        "nodes":[
            {
                "host":"34.224.50.110",
                "port":80,
                "weight":1
            },
            {
                "host":"18.205.98.194",
                "port":80,
                "weight":1
            }
        ],
        "type":"roundrobin",
        "checks":{
            "active":{
                "concurrency":10,
                "healthy":{
                    "http_statuses":[
                        200,
                        302
                    ],
                    "interval":1,
                    "successes":2
                },
                "http_path":"/get",
                "timeout":1,
                "type":"http",
                "unhealthy":{
                    "http_failures":5,
                    "http_statuses":[
                        429,
                        404,
                        500,
                        501,
                        502,
                        503,
                        504,
                        505
                    ],
                    "interval":1,
                    "tcp_failures":2,
                    "timeouts":3
                }
            }
        }
    }
}'

# breakpoint trigger logs
2023/02/24 14:52:44 [warn] 2385766#2385766: *44 [lua] [string "local dbg = require("apisix.inspect.dbg")..."]:240: clear traceback
stack traceback:
        /opt/apisix/apisix/inspect/dbg.lua:75: in function </opt/apisix/apisix/inspect/dbg.lua:41>
        /opt/apisix//deps/share/lua/5.1/resty/healthcheck.lua:434: in function </opt/apisix//deps/share/lua/5.1/resty/healthcheck.lua:432>
        [C]: in function 'pcall'
        /opt/apisix//deps/share/lua/5.1/resty/healthcheck.lua:249: in function 'run_fn_locked_target_list'
        /opt/apisix//deps/share/lua/5.1/resty/healthcheck.lua:273: in function 'clear'
        /opt/apisix/apisix/upstream.lua:85: in function 'f'
        /opt/apisix/apisix/core/config_util.lua:104: in function 'fire_all_clean_handlers'
        /opt/apisix/apisix/core/config_etcd.lua:464: in function 'sync_data'
        /opt/apisix/apisix/core/config_etcd.lua:606: in function </opt/apisix/apisix/core/config_etcd.lua:596>
        [C]: in function 'xpcall'
        /opt/apisix/apisix/core/config_etcd.lua:596: in function </opt/apisix/apisix/core/config_etcd.lua:574>, context: ngx.timer

Environment

  • APISIX version (run apisix version): master
  • Operating system (run uname -a):
  • OpenResty / Nginx version (run openresty -V or nginx -V):
  • etcd version, if relevant (run curl http://127.0.0.1:9090/v1/server_info):
  • APISIX Dashboard version, if relevant:
  • Plugin runner version, for issues related to plugin runners:
  • LuaRocks version, for installation issues (run luarocks --version):

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions