BUG/MEDIUM: listener: enforce rate-limit sessions across thread groups
Since session rates are accounted per thread group, the "rate-limit
sessions" check sums, for each group, the remaining budget computed
against the full configured limit. A frontend therefore keeps accepting
connections as long as any group stays below the limit:
- with evenly loaded groups, the frontend accepts up to the limit
multiplied by the number of thread groups;
- when some groups receive no traffic, e.g. with "bind ... thread
1/all" and several thread groups, the limit is never enforced.
No explicit thread group setting is needed to be affected. Since 3.3,
the default "performance" cpu-policy creates one thread group per CCX
when neither "nbthread" nor "thread-groups" is set, and binds are
spread over all groups. On machines with several CCX, a frontend with
no thread-related setting may thus accept several times its configured
session rate. Setting "thread-groups 1" works around the issue.
With "rate-limit sessions 100" and three thread groups, a local test
measured about 270 sessions/s on a bind using all groups, and more than
21000 sessions/s on a bind restricted to the first group.
The limit is meant to apply to the frontend as a whole. Let's sum the
per-group session totals first and compare the result with the limit,
both for the number of sessions that may still be accepted and for the
delay before the next one. Two helpers, proxy_fe_sess_remain() and
proxy_fe_sess_delay(), now do this for all callers. The same test then
measures 100 sessions/s in both cases.
A reg-test is provided: with a bind restricted to the first of two
thread groups and a limit of one session per second, the second session
must wait for the rate to drop and see fe_sess_rate at 1, not 2.
This was introduced in 3.3 by commit
16eb0fab3 ("MAJOR: counters:
dispatch counters over thread groups"), so this must be backported to
3.3.