Need some help in understanding stick table rate limit

We are using haproxy v 2.2

i have an frontend which handles few incoming APIS so i would like to control the limit in haproxy so that i can control my outgoing requests to outbound.

frontend http

bind 127.0.0.1:84 tfo accept-proxy
acl is_ssl fc_rcvd_proxy
option nolinger
stick-table type binary len 8 size 100k expire 10s store http_req_rate(1s)
http-request track-sc0 path
http-request set-var(req.rate_limit) path,map_regm(/usr/haproxyrates.map,500)
http-request set-var(req.request_rate) path,table_http_req_rate()
acl rate_abuse var(req.rate_limit),sub(req.request_rate) lt 0
acl is_rem path_reg /ann/user/[^/]+/remoteDestinations
http-request deny deny_status 503 if is_rem rate_abuse
use_backend slowBackHttp if rate_abuse

default_backend usemultipleports.

below is my contents of haproxyrates.map file
/ann/private/users 1
/ann/version 100
/ann/servers 100
/ann/user/[^/]+/remoteDestinations 3
/ann/private/options/userPolicy 80
/ann/private/user 80
/ann/user 30
/ann/clusterUser 10

i could see all my /ann/user/23/remoteDestinations API calls returned with 503 when i trigger this along with other api’s like /ann/clusterUser , /ann/user, /ann/private/user ,/ann/servers.

Any pointers here on what could be going wrong ?

Issue was also filed on Github and now seems resolved:


From your config:

stick-table type binary len 8 size 100k expire 10s store http_req_rate(1s)

Since table_http_req_rate() uses path as unique key, and that your setup involves long paths (more than 8 chars long), my guess is that 8 is too small to contain your various paths… thus all paths beginning with /ann/use* will match with the same stick table entry (and increase the same http request counter)

Please try increasing the stick table’s key length to a relevant value for your use-case so that all your paths end up being stored as distinct keys, or simply hash paths using a hashing function to store the key as “unique” fixed-length integers, like this:

frontend http

bind 127.0.0.1:84 tfo accept-proxy
acl is_ssl fc_rcvd_proxy
option nolinger
http-request set-var(req.path_key) path,xxh32 # convert path to integer using hashing function

stick-table type integer size 100k expire 10s store http_req_rate(1s) # key has integer type (lower memory footprint and faster lookup)
http-request track-sc0 var(req.path_key) # track using hash
acl remoteDestinations_ep1 path_end /remoteDestinations
http-request set-var(req.rate_limit) path,map_beg(/usr/haproxyrates.map,500) unless remoteDestinations_ep1
http-request set-var(req.rate_limit) int(10) if remoteDestinations_ep1
http-request set-var(req.request_rate) var(req.path_key),table_http_req_rate() # lookup using path
acl rate_abuse var(req.rate_limit),sub(req.request_rate) lt 0
#http-request deny deny_status 429 if rate_abuse
http-request deny deny_status 503 if rate_abuse remoteDestinations_ep1
use_backend slowservers if rate_abuse
default_backend usemultipleports.

Also please consider upgrading to the next LTS version because 2.2 will soon reach EOL.