Forum Discussion
Nigel88_321901
Apr 19, 2018Nimbostratus
iRule for rate limit unexpected behaviour
I have a requirement to implement rate limiting for HTTP requests and have acheived this somewhat through reading discussions and receving advice via this community. The iRules I have are not behavin...
Nigel88_321901
Apr 19, 2018Nimbostratus
iRule 2 https://devcentral.f5.com/questions/irule-rate-limiting-with-queuing-of-requests-57583comment64016:
when RULE_INIT {
Tweak the request limit and interval
set static::request_limit 30 ;count
set static::request_interval 1 ;sec
Tweak the queue size, timeout and retry interval
set static::queue_size 250 ;count
set static::queue_timeout 5 ;sec
set static::queue_retry_interval 1000 ;msec
}
when HTTP_REQUEST {
Enforce limits only on GET requests...
if { [HTTP::method] eq "GET" } then {
Calculate a unique request ID to track the request...
set request_id "[TMM::cmp_unit][clock clicks]"
Compute table labels for request and queued limiter...
set request_label "R_[HTTP::host]:[IP::client_addr]"
set queue_label "Q_[HTTP::host]"
Checking if request limit has been reached...
if { [set request_rate [table keys -count -subtable $request_label]] < $static::request_limit } then {
Max request rate is not exceeded. Insert a new entry to request limiter table...
table set -subtable $request_label $request_id "1" indef $static::request_interval
log local0.debug "Debug: $request_id : Allow: Request rate for $request_label is $request_rate / $static::request_interval seconds"
Allowing the request to pass...
} else {
Max request rate is exceeded. Holding the request to check queue slots...
log local0.debug "Debug: $request_id : Hold: Request rate for $request_label is $request_rate / $static::request_interval seconds"
Checking if queue has a free slot....
if { [set queue_size [table keys -count -subtable $queue_label]] < $static::queue_size } then {
Queue is not exceeded. Insert a new entry to queue limiter table...
table set -subtable $queue_label $request_id "1" indef $static::queue_timeout
log local0.debug "Debug: $request_id : Queued: Queue counter for $queue_label is $queue_size"
Initialize queue timer...
set queue_time 0
Enforcing the queue loop timeout timer...
while { $static::queue_timeout * 1000 > $queue_time } {
Pausing the ongoing HTTP request for queue retry interval
after $static::queue_retry_interval
Checking if request limit has been lowered...
if { [set request_rate [table keys -count -subtable $request_label]] < $static::request_limit } then {
Max request rate has been lowered. Insert a new entry to our request rate limiter...
table set -subtable $request_label $request_id "1" indef $static::request_interval
log local0.debug "Debug: $request_id : Queue Release: Requests rate for $request_label is now $request_rate / $static::request_interval seconds"
Removing this request from request queue
table delete -subtable $queue_label $request_id
Exiting this iRule and allowing the request to pass...
return
} else {
Max request rate is still exceeded. Queueing the request another cycle...
log local0.debug "Debug: $request_id : Queue Retry: Requests rate for $request_label is now $request_rate / $static::request_interval seconds"
incr queue_time $static::queue_retry_interval
}
}
Queued request has been timed out. Dropping the request...
log local0.debug "Debug: $request_id : Queue Fail: Requests rate for $request_label is now $request_rate / $static::request_interval seconds"
HTTP::respond 429 content "Request Denied: Exceeded requests/sec limits"
} else {
Maximum queue size has been exceeded. Dropping the request...
log local0.debug "Debug: $request_id : Queue Exceeded: Queue counter for $queue_label is $queue_size"
HTTP::respond 429 content "Request Denied: Exceeded requests/sec limits"
}
}
}
}
Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects