2019-08-30 09:40:29 +00:00
|
|
|
-- An affinity mode which makes sure a session is always routed to the same endpoint.
|
|
|
|
-- The advantage of this mode is that a user will never lose his session.
|
|
|
|
-- The drawback of this mode is that when scaling up a deployment, sessions will not
|
|
|
|
-- be rebalanced.
|
|
|
|
--
|
2019-08-30 16:07:24 +00:00
|
|
|
local balancer_sticky = require("balancer.sticky")
|
2023-11-07 14:33:22 +00:00
|
|
|
local balancer_round_robin = require("balancer.round_robin")
|
|
|
|
local balancer_chash = require("balancer.chash")
|
|
|
|
local balancer_chashsubset = require("balancer.chashsubset")
|
|
|
|
local balancer_ewma = require("balancer.ewma")
|
2019-09-24 08:46:02 +00:00
|
|
|
local util_get_nodes = require("util").get_nodes
|
2019-08-30 09:40:29 +00:00
|
|
|
local util_nodemap = require("util.nodemap")
|
2020-06-06 15:07:06 +00:00
|
|
|
local setmetatable = setmetatable
|
2019-08-30 09:40:29 +00:00
|
|
|
|
2023-11-07 14:33:22 +00:00
|
|
|
local function get_secondary_balancer(backend)
|
|
|
|
local name = backend["load-balance"]
|
|
|
|
|
|
|
|
if not name then return nil
|
|
|
|
elseif name == "chash" then return balancer_chash:new(backend)
|
|
|
|
elseif name == "chashsubset" then return balancer_chashsubset:new(backend)
|
|
|
|
elseif name == "round_robin" then return balancer_round_robin:new(backend)
|
|
|
|
elseif name == "ewma" then return balancer_ewma:new(backend)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-08-30 16:07:24 +00:00
|
|
|
local _M = balancer_sticky:new()
|
2019-08-30 09:40:29 +00:00
|
|
|
|
2019-08-30 16:07:24 +00:00
|
|
|
function _M.new(self, backend)
|
2019-09-24 08:46:02 +00:00
|
|
|
local nodes = util_get_nodes(backend.endpoints)
|
2019-08-30 16:07:24 +00:00
|
|
|
local hash_salt = backend["name"]
|
2023-11-07 14:33:22 +00:00
|
|
|
local secondary_balancer = get_secondary_balancer(backend)
|
2019-08-30 16:07:24 +00:00
|
|
|
|
|
|
|
local o = {
|
|
|
|
name = "sticky_persistent",
|
2023-11-07 14:33:22 +00:00
|
|
|
secondary_balancer = secondary_balancer,
|
2019-08-30 16:07:24 +00:00
|
|
|
instance = util_nodemap:new(nodes, hash_salt)
|
|
|
|
}
|
|
|
|
|
|
|
|
setmetatable(o, self)
|
|
|
|
self.__index = self
|
2019-08-30 17:08:03 +00:00
|
|
|
|
2019-08-30 16:07:24 +00:00
|
|
|
balancer_sticky.sync(o, backend)
|
|
|
|
|
|
|
|
return o
|
|
|
|
end
|
|
|
|
|
|
|
|
function _M.pick_new_upstream(self, failed_upstreams)
|
2023-11-07 14:33:22 +00:00
|
|
|
if self.secondary_balancer then
|
|
|
|
local endpoint = self.secondary_balancer:balance()
|
|
|
|
local key = self.instance:key_from_endpoint(endpoint)
|
|
|
|
if endpoint and key then
|
|
|
|
return endpoint, key
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-08-30 09:40:29 +00:00
|
|
|
return self.instance:random_except(failed_upstreams)
|
|
|
|
end
|
|
|
|
|
2023-11-07 14:33:22 +00:00
|
|
|
function _M.sync(self, backend)
|
2023-11-09 17:43:16 +00:00
|
|
|
-- sync inherited balancer
|
|
|
|
balancer_sticky.sync(self, backend)
|
|
|
|
|
|
|
|
-- note this may be inefficient
|
|
|
|
-- perhaps better to only update if name changes?
|
2023-11-07 14:33:22 +00:00
|
|
|
self.secondary_balancer = get_secondary_balancer(backend)
|
2023-11-09 17:43:16 +00:00
|
|
|
|
|
|
|
-- sync secondary_balancer as well
|
|
|
|
if self.secondary_balancer then
|
|
|
|
self.secondary_balancer:sync(backend)
|
|
|
|
end
|
2023-11-07 14:33:22 +00:00
|
|
|
end
|
|
|
|
|
2019-08-30 09:40:29 +00:00
|
|
|
return _M
|