From 3cbfd639923c8698e6fcb29f9728b171f1211e6d Mon Sep 17 00:00:00 2001 From: Henry Tran Date: Mon, 30 Jul 2018 15:55:47 -0400 Subject: [PATCH] Refactor EWMA to not use shared dictionaries --- .../ingress/controller/template/template.go | 2 - rootfs/etc/nginx/lua/balancer/ewma.lua | 59 +++---------------- .../etc/nginx/lua/test/balancer/ewma_test.lua | 16 ----- 3 files changed, 8 insertions(+), 69 deletions(-) diff --git a/internal/ingress/controller/template/template.go b/internal/ingress/controller/template/template.go index e6df56282..4dd3461e0 100644 --- a/internal/ingress/controller/template/template.go +++ b/internal/ingress/controller/template/template.go @@ -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", } diff --git a/rootfs/etc/nginx/lua/balancer/ewma.lua b/rootfs/etc/nginx/lua/balancer/ewma.lua index 270e990ca..352b654f7 100644 --- a/rootfs/etc/nginx/lua/balancer/ewma.lua +++ b/rootfs/etc/nginx/lua/balancer/ewma.lua @@ -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) diff --git a/rootfs/etc/nginx/lua/test/balancer/ewma_test.lua b/rootfs/etc/nginx/lua/test/balancer/ewma_test.lua index 920df1a92..d7cb8cab6 100644 --- a/rootfs/etc/nginx/lua/test/balancer/ewma_test.lua +++ b/rootfs/etc/nginx/lua/test/balancer/ewma_test.lua @@ -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)