I want to set limit of new users' connections if amount of active users exceeded the required threshold. Users connect to the load balancer via http. I use stick-table to limit the amount of users (by unique header):
frontend echo
bind *:8881
mode http
# user is active if seds any request every 30s or often
stick-table type string size 100k expire 30s store gpc0_rate(10s)
# track keys if table size less than limit
http-request track-sc0 req.hdr(Client-ID) if { table_cnt lt 100 }
# limit of new not active users
http-request deny deny_status 429 if { table_cnt ge 100 } { <❓check that "Client-ID" keys's value exists in the table> }
use_backend echo
The main idea is deny requests from all new user if Client-ID
header's value is not present in the table. It's possible?
You are close to solution. You need in_table converter:
Uses the string representation of the input sample to perform a look up in the specified table. If the key is not found in the table, a boolean false is returned. Otherwise a boolean true is returned. This can be used to verify the presence of a certain key in a table tracking some elements (e.g. whether or not a source IP address or an Authorization header was already seen).
In your case it would be one more acl: acl clientid_in_table req.hdr(client-id),in_table
and your config becomes (i prefer naming my ACLs for clarity):
frontend echo
bind *:8881
mode http
# user is active if seds any request every 30s or often
stick-table type string size 100k expire 30s store gpc0_rate(10s)
# ACL to check if client-id is in table
acl clientid_in_table req.hdr(client-id),in_table
# track keys if table size less than limit
http-request track-sc0 req.hdr(Client-ID) if { table_cnt lt 100 }
# limit of new not active users
http-request deny deny_status 429 if { table_cnt ge 100 } !clientid_in_table
use_backend echo
No idea what it does if header is missing in request, but you can deny it on that basis as well if needed.