Скажем, что тебе нужно вызывать функцию не чаще чем несколько раз в секунду, но иногда чаще, но не очень часто. А если все-таки часто, то ненадолго, чтобы потом снова медленно.
Простейший rate limit вида if (now - lastTime < 10) { return }
в такой ситуации не поможет.
На помощь приходит гениальный алгоритм Tocken bucket. Представь себе шкатулку, куда падает 1 жетон в секунду. В шкатулке помещается только 10 жетонов. Каждый вызов функции забирает 1 жетон.
Если шкатулка наполнена, то у тебя есть возможность вызвать функцию десять раз подряд без паузы (burst). Если она пустая, то функция будет вызываться раз в секунду, как только падает жетон (rate limit). Пришел покой — в шкатулке накопятся жетоны и снова появится возможность сделать burst.
Применение алгоритма — широчайшее.
Например, так сдерживают процессор на виртуальных машинах — чтобы на мелких виртуалках быстро отрабатывали всякие apt upgrade
, но чтобы они все равно оставались мелкими.
На таком же фундаментальном принципе основана защита от DoS-атак.
И так далее.