Dynamic LB sync non-external backends only when necessary

This commit is contained in:
Manuel Alejandro de Brito Fontes 2020-06-16 17:32:59 -04:00
parent 10dcf0db15
commit bcc3cfaa65
4 changed files with 91 additions and 6 deletions

View file

@ -23,6 +23,7 @@ local ngx = ngx
-- it will take <the delay until controller POSTed the backend object to the -- it will take <the delay until controller POSTed the backend object to the
-- Nginx endpoint> + BACKENDS_SYNC_INTERVAL -- Nginx endpoint> + BACKENDS_SYNC_INTERVAL
local BACKENDS_SYNC_INTERVAL = 1 local BACKENDS_SYNC_INTERVAL = 1
local BACKENDS_FORCE_SYNC_INTERVAL = 30
local DEFAULT_LB_ALG = "round_robin" local DEFAULT_LB_ALG = "round_robin"
local IMPLEMENTATIONS = { local IMPLEMENTATIONS = {
@ -36,6 +37,8 @@ local IMPLEMENTATIONS = {
local _M = {} local _M = {}
local balancers = {} local balancers = {}
local backends_with_external_name = {}
local backends_last_synced_at = 0
local function get_implementation(backend) local function get_implementation(backend)
local name = backend["load-balance"] or DEFAULT_LB_ALG local name = backend["load-balance"] or DEFAULT_LB_ALG
@ -92,6 +95,12 @@ local function format_ipv6_endpoints(endpoints)
return formatted_endpoints return formatted_endpoints
end end
local function is_backend_with_external_name(backend)
local serv_type = backend.service and backend.service.spec
and backend.service.spec["type"]
return serv_type == "ExternalName"
end
local function sync_backend(backend) local function sync_backend(backend)
if not backend.endpoints or #backend.endpoints == 0 then if not backend.endpoints or #backend.endpoints == 0 then
balancers[backend.name] = nil balancers[backend.name] = nil
@ -117,9 +126,7 @@ local function sync_backend(backend)
return return
end end
local service_type = backend.service and backend.service.spec if is_backend_with_external_name(backend) then
and backend.service.spec["type"]
if service_type == "ExternalName" then
backend = resolve_external_names(backend) backend = resolve_external_names(backend)
end end
@ -129,6 +136,17 @@ local function sync_backend(backend)
end end
local function sync_backends() local function sync_backends()
local raw_backends_last_synced_at = configuration.get_raw_backends_last_synced_at()
ngx.update_time()
local current_timestamp = ngx.time()
if current_timestamp - backends_last_synced_at < BACKENDS_FORCE_SYNC_INTERVAL
and raw_backends_last_synced_at <= backends_last_synced_at then
for _, backend_with_external_name in pairs(backends_with_external_name) do
sync_backend(backend_with_external_name)
end
return
end
local backends_data = configuration.get_backends_data() local backends_data = configuration.get_backends_data()
if not backends_data then if not backends_data then
balancers = {} balancers = {}
@ -145,13 +163,19 @@ local function sync_backends()
for _, new_backend in ipairs(new_backends) do for _, new_backend in ipairs(new_backends) do
sync_backend(new_backend) sync_backend(new_backend)
balancers_to_keep[new_backend.name] = balancers[new_backend.name] balancers_to_keep[new_backend.name] = balancers[new_backend.name]
if is_backend_with_external_name(new_backend) then
local backend_with_external_name = util.deepcopy(new_backend)
backends_with_external_name[backend_with_external_name.name] = backend_with_external_name
end
end end
for backend_name, _ in pairs(balancers) do for backend_name, _ in pairs(balancers) do
if not balancers_to_keep[backend_name] then if not balancers_to_keep[backend_name] then
balancers[backend_name] = nil balancers[backend_name] = nil
backends_with_external_name[backend_name] = nil
end end
end end
backends_last_synced_at = raw_backends_last_synced_at
end end
local function route_to_alternative_balancer(balancer) local function route_to_alternative_balancer(balancer)

View file

@ -24,6 +24,14 @@ function _M.get_general_data()
return configuration_data:get("general") return configuration_data:get("general")
end end
function _M.get_raw_backends_last_synced_at()
local raw_backends_last_synced_at = configuration_data:get("raw_backends_last_synced_at")
if raw_backends_last_synced_at == nil then
raw_backends_last_synced_at = 1
end
return raw_backends_last_synced_at
end
local function fetch_request_body() local function fetch_request_body()
ngx.req.read_body() ngx.req.read_body()
local body = ngx.req.get_body_data() local body = ngx.req.get_body_data()
@ -187,6 +195,16 @@ local function handle_backends()
return return
end end
ngx.update_time()
local raw_backends_last_synced_at = ngx.time()
success, err = configuration_data:set("raw_backends_last_synced_at", raw_backends_last_synced_at)
if not success then
ngx.log(ngx.ERR, "dynamic-configuration: error updating when backends sync, " ..
"new upstream peers waiting for force syncing: " .. tostring(err))
ngx.status = ngx.HTTP_BAD_REQUEST
return
end
ngx.status = ngx.HTTP_CREATED ngx.status = ngx.HTTP_CREATED
end end

View file

@ -18,6 +18,7 @@ local getmetatable = getmetatable
-- it will take <the delay until controller POSTed the backend object -- it will take <the delay until controller POSTed the backend object
-- to the Nginx endpoint> + BACKENDS_SYNC_INTERVAL -- to the Nginx endpoint> + BACKENDS_SYNC_INTERVAL
local BACKENDS_SYNC_INTERVAL = 1 local BACKENDS_SYNC_INTERVAL = 1
local BACKENDS_FORCE_SYNC_INTERVAL = 30
local DEFAULT_LB_ALG = "round_robin" local DEFAULT_LB_ALG = "round_robin"
local IMPLEMENTATIONS = { local IMPLEMENTATIONS = {
@ -26,6 +27,8 @@ local IMPLEMENTATIONS = {
local _M = {} local _M = {}
local balancers = {} local balancers = {}
local backends_with_external_name = {}
local backends_last_synced_at = 0
local function get_implementation(backend) local function get_implementation(backend)
local name = backend["load-balance"] or DEFAULT_LB_ALG local name = backend["load-balance"] or DEFAULT_LB_ALG
@ -65,6 +68,12 @@ local function format_ipv6_endpoints(endpoints)
return formatted_endpoints return formatted_endpoints
end end
local function is_backend_with_external_name(backend)
local serv_type = backend.service and backend.service.spec
and backend.service.spec["type"]
return serv_type == "ExternalName"
end
local function sync_backend(backend) local function sync_backend(backend)
if not backend.endpoints or #backend.endpoints == 0 then if not backend.endpoints or #backend.endpoints == 0 then
return return
@ -89,9 +98,7 @@ local function sync_backend(backend)
return return
end end
local service_type = backend.service and backend.service.spec and if is_backend_with_external_name(backend) then
backend.service.spec["type"]
if service_type == "ExternalName" then
backend = resolve_external_names(backend) backend = resolve_external_names(backend)
end end
@ -101,6 +108,17 @@ local function sync_backend(backend)
end end
local function sync_backends() local function sync_backends()
local raw_backends_last_synced_at = configuration.get_raw_backends_last_synced_at()
ngx.update_time()
local current_timestamp = ngx.time()
if current_timestamp - backends_last_synced_at < BACKENDS_FORCE_SYNC_INTERVAL
and raw_backends_last_synced_at <= backends_last_synced_at then
for _, backend_with_external_name in pairs(backends_with_external_name) do
sync_backend(backend_with_external_name)
end
return
end
local backends_data = configuration.get_backends_data() local backends_data = configuration.get_backends_data()
if not backends_data then if not backends_data then
balancers = {} balancers = {}
@ -117,13 +135,19 @@ local function sync_backends()
for _, new_backend in ipairs(new_backends) do for _, new_backend in ipairs(new_backends) do
sync_backend(new_backend) sync_backend(new_backend)
balancers_to_keep[new_backend.name] = balancers[new_backend.name] balancers_to_keep[new_backend.name] = balancers[new_backend.name]
if is_backend_with_external_name(new_backend) then
local backend_with_external_name = util.deepcopy(new_backend)
backends_with_external_name[backend_with_external_name.name] = backend_with_external_name
end
end end
for backend_name, _ in pairs(balancers) do for backend_name, _ in pairs(balancers) do
if not balancers_to_keep[backend_name] then if not balancers_to_keep[backend_name] then
balancers[backend_name] = nil balancers[backend_name] = nil
backends_with_external_name[backend_name] = nil
end end
end end
backends_last_synced_at = raw_backends_last_synced_at
end end
local function get_balancer() local function get_balancer()

View file

@ -9,6 +9,14 @@ function _M.get_backends_data()
return tcp_udp_configuration_data:get("backends") return tcp_udp_configuration_data:get("backends")
end end
function _M.get_raw_backends_last_synced_at()
local raw_backends_last_synced_at = tcp_udp_configuration_data:get("raw_backends_last_synced_at")
if raw_backends_last_synced_at == nil then
raw_backends_last_synced_at = 1
end
return raw_backends_last_synced_at
end
function _M.call() function _M.call()
local sock, err = ngx.req.socket(true) local sock, err = ngx.req.socket(true)
if not sock then if not sock then
@ -35,6 +43,17 @@ function _M.call()
ngx.say("error: ", err_conf) ngx.say("error: ", err_conf)
return return
end end
ngx.update_time()
local raw_backends_last_synced_at = ngx.time()
success, err = tcp_udp_configuration_data:set("raw_backends_last_synced_at",
raw_backends_last_synced_at)
if not success then
ngx.log(ngx.ERR, "dynamic-configuration: error updating when backends sync, " ..
"new upstream peers waiting for force syncing: " .. tostring(err))
ngx.status = ngx.HTTP_BAD_REQUEST
return
end
end end
return _M return _M