Skip to content

Instantly share code, notes, and snippets.

@victorhazbun
Forked from mperham/Benchmark.rb
Created October 7, 2023 18:44
Show Gist options
  • Save victorhazbun/4f47f64b34096610aa40420acc19ad45 to your computer and use it in GitHub Desktop.
Save victorhazbun/4f47f64b34096610aa40420acc19ad45 to your computer and use it in GitHub Desktop.
Leaky bucket limiter usage with Sidekiq Enterprise
require 'benchmark'
require 'sidekiq-ent/limiter'
COUNT = 10_000
Benchmark.bmbm(30) do |x|
x.report("leaky") do
COUNT.times do |count|
lmt = Sidekiq::Limiter.leaky("leaky_#{count%100}", 10, 10, wait_timeout: 0, policy: :skip)
lmt.within_limit do
# do nothing
end
end
end
x.report("bucket") do
COUNT.times do |count|
lmt = Sidekiq::Limiter.bucket("bucket#{count%100}", 10, :second, wait_timeout: 0, policy: :skip)
lmt.within_limit do
# do nothing
end
end
end
x.report("window") do
COUNT.times do |count|
lmt = Sidekiq::Limiter.window("window#{count%100}", 10, :second, wait_timeout: 0, policy: :skip)
lmt.within_limit do
# do nothing
end
end
end
end
> bundle exec ruby bench.rb
Rehearsal ------------------------------------------------------------------
leaky 0.710620 0.155588 0.866208 ( 1.239325)
bucket 1.648613 0.409582 2.058195 ( 2.285934)
window 2.185998 0.604629 2.790627 ( 3.015270)
--------------------------------------------------------- total: 5.715030sec
user system total real
leaky 0.705626 0.155107 0.860733 ( 1.225562)
bucket 1.651114 0.418390 2.069504 ( 2.331178)
window 2.140379 0.590244 2.730623 ( 2.929512)
# This file is used by Rack-based servers to start the application.
# Run with `bundle exec rackup simple.ru`
# NB: this requires Sidekiq Enterprise v2.2+
require 'rack/urlmap'
require "sidekiq-ent/limiter"
require "sidekiq-ent/web"
# configure the Redis instance used by rate limiting
Sidekiq::Limiter.configure do |config|
config.redis = { port: 6379, db: 4 }
end
class LeakyLimiter
def initialize(app)
@app = app
end
def call(env)
remote_ip = env["REMOTE_ADDR"].tr(':', '_')
begin
limiter = Sidekiq::Limiter.leaky("ip-#{remote_ip}", 10, 10, wait_timeout: 0)
limiter.within_limit do
@app.call(env)
end
rescue Sidekiq::Limiter::OverLimit => ex
[429, {
"Content-Type" => "text/plain",
"X-Rate-Limited-For" => ex.limiter.next_drip.to_s,
}, ["Rate limited\r\n"]]
end
end
end
use LeakyLimiter
run Rack::URLMap.new({
"/sidekiq" => Sidekiq::Web,
"/api" => proc{|env| [200, {}, ["Hello world\r\n"]] },
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment