PERF: improve performance once logged in rate limiter hits
If "logged in" is being forced anonymous on certain routes, trigger the protection for any requests that spend 50ms queueing This means that ... 1. You need to trip it by having 3 requests take longer than 1 second in 10 second interval 2. Once tripped, if your route is still spending 50m queueuing it will continue to be protected This means that site will continue to function with almost no delays while it is scaling up to handle the new load
This commit is contained in:
parent
d0353fb2f2
commit
ded84a4b58
|
@ -198,7 +198,7 @@ max_reqs_rate_limit_on_private = false
|
||||||
# logged in DoS protection
|
# logged in DoS protection
|
||||||
|
|
||||||
# protection will only trigger for requests that queue longer than this amount
|
# protection will only trigger for requests that queue longer than this amount
|
||||||
force_anonymous_min_queue_seconds = 2
|
force_anonymous_min_queue_seconds = 1
|
||||||
# only trigger anon if we see more than N requests for this path in last 10 seconds
|
# only trigger anon if we see more than N requests for this path in last 10 seconds
|
||||||
force_anonymous_min_per_10_seconds = 3
|
force_anonymous_min_per_10_seconds = 3
|
||||||
|
|
||||||
|
|
|
@ -104,20 +104,29 @@ module Middleware
|
||||||
request.delete_param('api_key')
|
request.delete_param('api_key')
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_logged_in_rate_limit!
|
def logged_in_anon_limiter
|
||||||
limiter = RateLimiter.new(
|
@logged_in_anon_limiter ||= RateLimiter.new(
|
||||||
nil,
|
nil,
|
||||||
"logged_in_anon_cache_#{@env["HOST"]}/#{@env["REQUEST_URI"]}",
|
"logged_in_anon_cache_#{@env["HOST"]}/#{@env["REQUEST_URI"]}",
|
||||||
GlobalSetting.force_anonymous_min_per_10_seconds,
|
GlobalSetting.force_anonymous_min_per_10_seconds,
|
||||||
10
|
10
|
||||||
)
|
)
|
||||||
!limiter.performed!(raise_error: false)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_logged_in_rate_limit!
|
||||||
|
!logged_in_anon_limiter.performed!(raise_error: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
MIN_TIME_TO_CHECK = 0.05
|
||||||
|
|
||||||
def should_force_anonymous?
|
def should_force_anonymous?
|
||||||
if queue_time = @env['REQUEST_QUEUE_SECONDS']
|
if (queue_time = @env['REQUEST_QUEUE_SECONDS']) && get?
|
||||||
if queue_time > GlobalSetting.force_anonymous_min_queue_seconds && get?
|
if queue_time > GlobalSetting.force_anonymous_min_queue_seconds
|
||||||
return check_logged_in_rate_limit!
|
return check_logged_in_rate_limit!
|
||||||
|
elsif queue_time >= MIN_TIME_TO_CHECK
|
||||||
|
if !logged_in_anon_limiter.can_perform?
|
||||||
|
return check_logged_in_rate_limit!
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -79,18 +79,37 @@ describe Middleware::AnonymousCache::Helper do
|
||||||
"rack.input" => StringIO.new
|
"rack.input" => StringIO.new
|
||||||
}
|
}
|
||||||
|
|
||||||
app.call(env)
|
is_anon = false
|
||||||
|
app.call(env.dup)
|
||||||
expect(is_anon).to eq(false)
|
expect(is_anon).to eq(false)
|
||||||
|
|
||||||
app.call(env)
|
is_anon = false
|
||||||
|
app.call(env.dup)
|
||||||
expect(is_anon).to eq(false)
|
expect(is_anon).to eq(false)
|
||||||
|
|
||||||
app.call(env)
|
is_anon = false
|
||||||
|
app.call(env.dup)
|
||||||
expect(is_anon).to eq(true)
|
expect(is_anon).to eq(true)
|
||||||
|
|
||||||
_status, headers, _body = app.call(env)
|
is_anon = false
|
||||||
|
_status, headers, _body = app.call(env.dup)
|
||||||
expect(is_anon).to eq(true)
|
expect(is_anon).to eq(true)
|
||||||
expect(headers['Set-Cookie']).to eq('dosp=1')
|
expect(headers['Set-Cookie']).to eq('dosp=1')
|
||||||
|
|
||||||
|
# tricky change, a 50ms delay still will trigger protection
|
||||||
|
# once it is tripped
|
||||||
|
|
||||||
|
env["REQUEST_QUEUE_SECONDS"] = 0.05
|
||||||
|
is_anon = false
|
||||||
|
|
||||||
|
app.call(env.dup)
|
||||||
|
expect(is_anon).to eq(true)
|
||||||
|
|
||||||
|
is_anon = false
|
||||||
|
env["REQUEST_QUEUE_SECONDS"] = 0.01
|
||||||
|
|
||||||
|
app.call(env.dup)
|
||||||
|
expect(is_anon).to eq(false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue