Merge pull request #3295 from Shopify/ewma-without-shared-dict

Refactor EWMA to not use shared dictionaries
This commit is contained in:
k8s-ci-robot 2018-10-26 10:47:17 -07:00 committed by GitHub
commit 645f69ba76
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 8 additions and 69 deletions

View file

@ -209,8 +209,6 @@ func buildLuaSharedDictionaries(s interface{}, disableLuaRestyWAF bool) string {
"lua_shared_dict configuration_data 5M",
"lua_shared_dict certificate_data 16M",
"lua_shared_dict locks 512k",
"lua_shared_dict balancer_ewma 1M",
"lua_shared_dict balancer_ewma_last_touched_at 1M",
"lua_shared_dict sticky_sessions 1M",
}

View file

@ -5,38 +5,17 @@
-- /finagle-core/src/main/scala/com/twitter/finagle/loadbalancer/PeakEwma.scala
local resty_lock = require("resty.lock")
local util = require("util")
local split = require("util.split")
local DECAY_TIME = 10 -- this value is in seconds
local LOCK_KEY = ":ewma_key"
local PICK_SET_SIZE = 2
local ewma_lock = resty_lock:new("locks", {timeout = 0, exptime = 0.1})
local balancer_ewma = {}
local balancer_ewma_last_touched_at = {}
local _M = { name = "ewma" }
local function lock(upstream)
local _, err = ewma_lock:lock(upstream .. LOCK_KEY)
if err then
if err ~= "timeout" then
ngx.log(ngx.ERR, string.format("EWMA Balancer failed to lock: %s", tostring(err)))
end
end
return err
end
local function unlock()
local ok, err = ewma_lock:unlock()
if not ok then
ngx.log(ngx.ERR, string.format("EWMA Balancer failed to unlock: %s", tostring(err)))
end
return err
end
local function decay_ewma(ewma, last_touched_at, rtt, now)
local td = now - last_touched_at
td = (td > 0) and td or 0
@ -47,40 +26,18 @@ local function decay_ewma(ewma, last_touched_at, rtt, now)
end
local function get_or_update_ewma(upstream, rtt, update)
local lock_err = nil
if update then
lock_err = lock(upstream)
end
local ewma = ngx.shared.balancer_ewma:get(upstream) or 0
if lock_err ~= nil then
return ewma, lock_err
end
local ewma = balancer_ewma[upstream] or 0
local now = ngx.now()
local last_touched_at = ngx.shared.balancer_ewma_last_touched_at:get(upstream) or 0
local last_touched_at = balancer_ewma_last_touched_at[upstream] or 0
ewma = decay_ewma(ewma, last_touched_at, rtt, now)
if not update then
return ewma, nil
end
local success, err, forcible = ngx.shared.balancer_ewma_last_touched_at:set(upstream, now)
if not success then
ngx.log(ngx.WARN, "balancer_ewma_last_touched_at:set failed " .. err)
end
if forcible then
ngx.log(ngx.WARN, "balancer_ewma_last_touched_at:set valid items forcibly overwritten")
end
success, err, forcible = ngx.shared.balancer_ewma:set(upstream, ewma)
if not success then
ngx.log(ngx.WARN, "balancer_ewma:set failed " .. err)
end
if forcible then
ngx.log(ngx.WARN, "balancer_ewma:set valid items forcibly overwritten")
end
unlock()
balancer_ewma_last_touched_at[upstream] = now
balancer_ewma[upstream] = ewma
return ewma, nil
end
@ -153,8 +110,8 @@ function _M.sync(self, backend)
self.peers = backend.endpoints
-- TODO: Reset state of EWMA per backend
ngx.shared.balancer_ewma:flush_all()
ngx.shared.balancer_ewma_last_touched_at:flush_all()
balancer_ewma = {}
balancer_ewma_last_touched_at = {}
end
function _M.new(self, backend)

View file

@ -26,10 +26,6 @@ describe("Balancer ewma", function()
local instance = balancer_ewma:new(backend)
local stats = { ["10.184.7.40:8080"] = 0.5, ["10.184.97.100:8080"] = 0.3 }
ngx.shared.balancer_ewma.get = function(self, key) return stats[key] end
local t = ngx.now()-10
ngx.shared.balancer_ewma_last_touched_at.get = function(self, key) return t end
local peer = instance:balance()
assert.equal("10.184.97.100:8080", peer)
@ -52,13 +48,7 @@ describe("Balancer ewma", function()
endpoints = { { address = "10.184.7.40", port = "8080", maxFails = 0, failTimeout = 0 } }
}
local s1 = spy.on(ngx.shared.balancer_ewma, "flush_all")
local s2 = spy.on(ngx.shared.balancer_ewma_last_touched_at, "flush_all")
instance:sync(new_backend)
assert.spy(s1).was_not_called()
assert.spy(s2).was_not_called()
end)
it("updates endpoints", function()
@ -77,13 +67,7 @@ describe("Balancer ewma", function()
local new_backend = util.deepcopy(backend)
new_backend.endpoints[1].maxFails = 3
local s1 = spy.on(ngx.shared.balancer_ewma, "flush_all")
local s2 = spy.on(ngx.shared.balancer_ewma_last_touched_at, "flush_all")
instance:sync(new_backend)
assert.spy(s1).was_called()
assert.spy(s2).was_called()
end)
end)
end)