<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div>The tricky question is about how much overload you might be expecting. The thing is that accepting an HTTP request and parsing it in order to know where it goes is a relatively costly operation (compared to just paying $2, getting a few thousand AWS instances, and throwing pre-built garbage queries at a server somewhere).</div><div><br></div><div>If what you're trying to do is absorb and track HTTP traffic to put a cap on even costlier operations at the back-end (or on servers upstream) such as costly processing or DB queries, then you don't necessarily need to be super fast; you just need to be cheaper than the big costly operations you're trying to protect against.</div><div><br></div><div>There are various strategies there depending on how slow you can afford to be, many of which have been described here:</div><div><ul><li>using a gen_server to track and count (riskier on large servers as it may represent a single point of contention)</li><li>Jobs, which can be augmented with a lot of probes</li><li>Locks taken and handled with ETS</li><li>Circuit breakers to look at various metrics to force input to stall when becoming unstable</li></ul><div>I've written a blog post that tracks most mechanism available for overload handling and flow control there: <a href="https://ferd.ca/handling-overload.html">https://ferd.ca/handling-overload.html</a></div><div><br></div><div>And at Heroku, we also developed a locking library (also in the blog post above) named canal_lock (<a href="https://github.com/heroku/canal_lock">https://github.com/heroku/canal_lock</a>) which was aimed at being able to do lock-management for backend services where the number of available nodes changes and adapts over time. Still, if you can afford it, circuit breakers or frameworks like jobs do a good there since they can adapt with a lot of local-only information (and approaches such as <a href="https://en.wikipedia.org/wiki/Additive_increase/multiplicative_decrease">https://en.wikipedia.org/wiki/Additive_increase/multiplicative_decrease</a> for self-regulation. Also look at CoDel and other algorithms) <br></div><div><br></div><div>But all of this won't necessarily go far if what you have is overload traffic that is too costly to handle directly in terms of "parsing all the HTTP Requests is already too much CPU". Then you need to move to cheaper means: track connections or per-domain traffic through SNI data rather than plain HTTP requests, and impose limits there. Turn on options such as TCP_DEFER_ACCEPT which tell the kernel not to return you an 'accepted' socket until it has data waiting on the line, which saves on context switching and prevents idle connections from going up to your app (but won't do much if you're using TLS or the PROXY protocol since they expect to send info down the line right away).</div><div><br></div><div>When that won't work, you'll need to go down to the OS-level. You can tweak the size of ACK and SYN queues for indiscriminate filtering, or use packet filtering rules where the kernel itself can do quick inspection and dropping of data you cannot accept based on some data they contain. If you're at that level though, you may need a second NIC that is privately accessible just in order to be able to go set and modify these rules while the public NIC is under stress. If that doesn't work, then you need to look at a broader scope in terms of what your data center can do, but I figure this gets far from what you needed here.</div><div><br></div><div>In any case, the critical bit is that your system can be modeled as a queuing system; if you want to be able to take control over its stability, you must have the ability to handle validation and expulsion of overflow tasks faster than they can arrive. If you can't do that, you will not control what it is that you drop in terms of overflow. Any point of asynchrony in your system can act as an open valve where a task is reported to go fast when it goes sit into a growing queue down somewhere, so you have to be careful and make sure that your control and filtering at the edge reflects your actual bottlenecks and loads down the line.<br></div></div></div></div></div></div><br><div class="gmail_quote"><div dir="ltr">On Fri, Sep 21, 2018 at 2:40 AM Frank Muller <<a href="mailto:frank.muller.erl@gmail.com">frank.muller.erl@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto">Hi guys</div><div dir="auto"><br></div><div dir="auto">We have an HTTP web service based Cowboy which is receiving more and more traffic.</div><div dir="auto"><br></div><div dir="auto">We would like to implement a throttling mechanism per IP address to limit how many request/sec the same IP address can make.</div><div dir="auto"><br></div><div dir="auto">Is there any library out there for that?</div><div dir="auto">Or any (simple yet efficient) algorithm to implement?</div><div dir="auto"><br></div><div dir="auto">Ideas & feedabacks are very welcome. </div><div dir="auto"><br></div><div dir="auto">Thanks in advance.</div><div dir="auto"><br></div><div dir="auto">/Frank</div>
_______________________________________________<br>
erlang-questions mailing list<br>
<a href="mailto:erlang-questions@erlang.org" target="_blank">erlang-questions@erlang.org</a><br>
<a href="http://erlang.org/mailman/listinfo/erlang-questions" rel="noreferrer" target="_blank">http://erlang.org/mailman/listinfo/erlang-questions</a><br>
</blockquote></div>