On 08.06.20 09:15, Stefano Tranquillini wrote: > > > On Sun, Jun 7, 2020 at 11:11 PM Илья Шипицин <[email protected] > <mailto:[email protected]>> wrote: > > > > вс, 7 июн. 2020 г. в 19:59, Stefano Tranquillini <[email protected] > <mailto:[email protected]>>: > > Hello all, > > I'm moving to HA using it to replace NGINX and I've a question > regarding how to do a Rate Limiting in HA that enables queuing the requests > instead of closing them. > > I was able to limit per IP following those examples: > https://www.haproxy.com/blog/four-examples-of-haproxy-rate-limiting/ . > However, when the limit is reached, the users see the error and connection is > closed. > > Since I come from NGINX, it has this handy feature > https://www.nginx.com/blog/rate-limiting-nginx/ where connections that exceed > the threshold are queued. Thus the user will still be able to do the calls > but be delayed without him getting errors and keep the overall number of > requests within threshold. > > Is there anything similar in HA? It should limit/queueing the user by > IP. > > To explain with an example, we have two users |Alice|, with ip > |A.A.A.A| and |Bob| with ip |B.B.B.B| The threshold is |30r/minute|. > > So in 1 minute: > > * Alice does 20 requests. -> that's fine > * Bob does 60 requests. -> the system caps the requset to 30 and > then process the other 30 later on (maybe also adding timeout/delay) > * Alice does 50 request -> the first 40 are fine, the next 10 are > queued. > * Bob does 20 requests -> they are queue after the one above. > > I saw that it can be done in general, by limiting the connections per > host. But this will mean that it's cross IP and thus, if 500 is the limit > - Alice does 1 call > - Bob does 1000 calls > - Alice does another 1 call > - Alice will be queued, that's not what i would like to have. > > is this possible? Is there anything similar that can be done? > > > it is not cross IP. I wish nginx docs would be better on that. > > What do you mean? > in nginx i do > limit_req_zone $binary_remote_addr zone=prod:10m rate=40r/m; > and works > > first, in nginx terms it is limited by zone key. you can define key using > for example $binary_remote_addr$http_user_agent$ssl_client_ciphers > that means each unique combination of those parameters will be limited by > its own counter (or you can use nginx maps to construct such a zone key) > > in haproxy you can see and example of > > # Track client by base32+src (Host header + URL path + src IP) > > http-requesttrack-sc0 base32+src > > which also means key definition may be as flexible as you can imagine. > > > the point is, how can i cap the number of requests for a single user to > 40r/minute for example? or any number. > > What I was able to do is to slow it down in this way, but it does not ensure > the cap per request, it only adds 500ms to each call. > > frontend proxy > bind *:80 > # ACL function declarations > acl is_first_level src_http_req_rate(Abuse) ge 30 > use_backend api_delay if is_first_level > use_backend api > > backend api > server api01 api01:80 > server api02 api02:80 > server api03 api03:80 > > backend api_delay > tcp-request inspect-delay 500ms > tcp-request content accept if WAIT_END > server api01 api01:80 > server api02 api02:80 > server api03 api03:80 > > backend Abuse > stick-table type ip size 100k expire 15s store http_req_rate(10s)
I would try to use "http-request set-priority-class" and/or "http-request set-priority-offset" for this. http://cbonte.github.io/haproxy-dconv/2.1/configuration.html#4.2-http-request%20set-priority-class http://cbonte.github.io/haproxy-dconv/2.1/configuration.html#4.2-http-request%20set-priority-offset ``` acl is_first_level src_http_req_rate(Abuse) ge 30 http-request set-priority int(20) if is_first_level ``` In the mailing list archive is a example how to use it https://www.mail-archive.com/[email protected]/msg29915.html Sorry that I can't give you a better solution but I never used it so it would be nice to get feedback if this options works for your use case > > Thanks > -- > *Stefano* > -- > Stefano Regards Aleks

