lua-resty-upstream-healthcheck icon indicating copy to clipboard operation
lua-resty-upstream-healthcheck copied to clipboard

Feature request: support dynamic upstream

Open timebug opened this issue 3 years ago • 2 comments

Hi,

The current usage scenario assumes that the upstream configuration will not change dynamically, we only can change upstream configuration via reload nginx.

In some scenarios (see also https://github.com/openresty/lua-resty-upstream-healthcheck/issues/55), we want to dynamically modify the upstream configuration without reload nginx, and the current design cannot satisfy it, so can we add a parameter to hc.spawn_checker to support dynamic upstream mode?

case1: support upstream modify only

  • Module: https://github.com/openresty/lua-upstream-nginx-module (TODO)
  • Module: https://github.com/weibocom/nginx-upsync-module
  • NGINX Plus: https://docs.nginx.com/nginx/admin-guide/load-balancer/dynamic-configuration-api/

In this case, just add a parameter to hc.spawn_checker:

init_worker_by_lua_block {
    local us, err = get_upstreams()
    if not us then
        return
    end

    for _, u in ipairs(us) do
        local ok, err = hc.spawn_checker{
            shm = "healthcheck",
            type = "http",
            upstream = u,

            dynamic = true, -- enable dynamic upstream mode
        }
    end
}

case2: support upstream add/delete/modify

  • Module: https://github.com/yzprofile/ngx_http_dyups_module
  • Tengine: https://tengine.taobao.org/document/http_dyups.html

In this case, we should add a timer to watch global upstream configuration:

init_worker_by_lua_block {
    require "resty.core"

    local upstream = require "ngx.upstream"
    local hc = require "resty.upstream.healthcheck"

    local get_upstreams = upstream.get_upstreams

    local watch
    watch = function (premature)
        if premature then
            return
        end

        local us, err = get_upstreams()
        if not us then
            return
        end

        for _, u in ipairs(us) do
            local ok, err = hc.spawn_checker{
                shm = "healthcheck",
                type = "http",
                upstream = u,

                dynamic = true, -- enable dynamic upstream mode
            }
        end

        local ok, err = ngx.timer.at(2, watch)
    end

    local ok, err = ngx.timer.at(2, watch) -- create a timer to watch global upstream configuration every 2s.
}

Dynamic upstream mode checker behave as follows:

  • When call spawn_checker, if the upstream not exists, new checker will be created, otherwise ignore. (case1)
  • Any time, when delete an upstream, the checker will exit automatically. (case 1)
  • Any time, when modify an upstream (compared with peers md5 digest), the checker will update peers automatically. (case1 + case2)

timebug avatar Oct 10 '20 13:10 timebug

cc @agentzh @spacewander If you are interested in this, I can submit a PR.

timebug avatar Oct 10 '20 13:10 timebug

I have the same requirements. Can you send the modified healthcheck? @timebug

kys1230 avatar Apr 12 '22 08:04 kys1230