Ограничение скорости с Луа - PullRequest
3 голосов
/ 04 июля 2019

Мы внедрили ограничение скорости на основе Redis для нашего веб-сервиса, которое было взято с здесь . Я дублирую соответствующий код здесь.

local limits = cjson.decode(ARGV[1])
local now = tonumber(ARGV[2])
local weight = tonumber(ARGV[3] or '1')
local longest_duration = limits[1][1] or 0
local saved_keys = {}
-- handle cleanup and limit checks
for i, limit in ipairs(limits) do

local duration = limit[1]
longest_duration = math.max(longest_duration, duration)
local precision = limit[3] or duration
precision = math.min(precision, duration)
local blocks = math.ceil(duration / precision)
local saved = {}
table.insert(saved_keys, saved)
saved.block_id = math.floor(now / precision)
saved.trim_before = saved.block_id - blocks + 1
saved.count_key = duration .. ':' .. precision .. ':'
saved.ts_key = saved.count_key .. 'o'
for j, key in ipairs(KEYS) do

    local old_ts = redis.call('HGET', key, saved.ts_key)
    old_ts = old_ts and tonumber(old_ts) or saved.trim_before
    if old_ts > now then
        -- don't write in the past
        return 1
    end

    -- discover what needs to be cleaned up
    local decr = 0
    local dele = {}
    local trim = math.min(saved.trim_before, old_ts + blocks)
    for old_block = old_ts, trim - 1 do
        local bkey = saved.count_key .. old_block
        local bcount = redis.call('HGET', key, bkey)
        if bcount then
            decr = decr + tonumber(bcount)
            table.insert(dele, bkey)
        end
    end

    -- handle cleanup
    local cur
    if #dele > 0 then
        redis.call('HDEL', key, unpack(dele))
        cur = redis.call('HINCRBY', key, saved.count_key, -decr)
    else
        cur = redis.call('HGET', key, saved.count_key)
    end

    -- check our limits
    if tonumber(cur or '0') + weight > limit[2] then
        return 1
    end
  end
end

Я пытаюсь выяснить смысл комментария - не писать в прошлом Я не понимаю, как возможен случай, когда old_ts больше now Я поместил логи по всему коду lua, но безуспешно.

Максимум old_ts может быть равен saved.trim_before, что, в свою очередь, может быть равно now, если precision равно 1 и blocks равно 1. Но не больше. Было бы полезно, если у кого-то есть понимание этого.

1 Ответ

0 голосов
/ 14 июля 2019

Если вы посмотрите на суть, приведенную в статье

https://gist.github.com/josiahcarlson/80584b49da41549a7d5c

Есть комментарий, который спрашивает

In over_limit_sliding_window_lua_, should

if old_ts > now then

at here be

if old_ts > saved.block_id then

И я согласен с этим, old_ts должен иметь bucket, и когда корзина переходит к следующему слоту, то есть, когда old_ts будет больше, чем block_id

...