<div dir="ltr"><div><div><div><div><div><div><div><div><div>To be more concrete:<br><br></div>Amazon might have a fancy ALB load balancer.<br><br></div>Amazon might also use HTTP/2 in that fancy ALB load balancer.<br><br></div>HTTP/2 has a flow control system because you are muxing several streams into one TCP connection. Also note that TCP has a send window.<br><br></div>Amazon might have defaulted their HTTP/2 Window frames to 16kilobyte in the upload direction.<br><br></div>If you do the tcp plots, this leads to a fun situation where the packets are flapping between MSS and ack-only packets, and your speed is limited by the RTT of the line.<br><br></div>People running gRPC knows that "using the Amazon layer 4 load balancer works", but they have yet to analyze the problem further. They know it "doesn't work with HTTP/2".<br><br></div>gRPC has its own flow control (!!) on top of HTTP/2, because "gRPC has to be transport agnostic in case you want to use UDP".<br><br></div>The end result is that you are not running at maximal utilization of the underlying TCP connection.<br><br>...<br><br></div>Another thing to think about: If you employ flow control, you have to think about the "lock" situation in which the flow control locks up the system. If the sender can be flow controlled, the problem is twofold at sender and at receiver side. This interaction is somewhat complex, compared to interaction in one side only. Corollary: Go, with bounded channels, have way more points where quasi-deadlock can occur than an Erlang program. But the Erlang program can overflow its mailbox in contrast.<br><br></div><br><div class="gmail_quote"><div dir="ltr">On Mon, Jan 22, 2018 at 3:25 PM Fred Hebert <<a href="mailto:mononcqc@ferd.ca">mononcqc@ferd.ca</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">I have written Handling Overload (<a href="https://ferd.ca/handling-overload.html" target="_blank">https://ferd.ca/handling-overload.html</a>) as tour of the multiple options in Erlang. It may prove helpful.<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jan 22, 2018 at 4:52 AM, Karl Nilsson <span dir="ltr"><<a href="mailto:kjnilsson@gmail.com" target="_blank">kjnilsson@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Thanks Jesper, keeping flow control to the input edge makes perfect sense to me but developing a good feedback mechanism that is both safe and not overly cautious is likely to be quite challenging in non-trivial, potentially distributed domains.<div><br></div><div>I have some thinking to do. :) Any further reading along these lines that anyone knows of would be very welcome.</div><div><div class="m_6648783237993695589h5"><div><br><div class="gmail_quote"><div dir="ltr">On Fri, 19 Jan 2018 at 21:17 Jesper Louis Andersen <<a href="mailto:jesper.louis.andersen@gmail.com" target="_blank">jesper.louis.andersen@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="ltr">As Lukas already wrote on slack somewhere:<div><br></div><div>Imagine you have a 2000'es machine: single core, around 400 mhz if you are lucky. In that setting, sender punishment can in some situations rectify a system that is going overboard. We simply let the offending process have less time on the scheduler in the hope that the overloaded mailbox process can catch up and do its work. It is not a surefire solution, but it may avoid some situations in which the system would otherwise topple.</div><div><br></div><div>Fast forward 18 years. Now, the machines are multicore, at least 4 threads commonly. Here, a sender might live on one core whereas the reciever might live on another process. It is less clear why the punishment strategy is good: we get to stop the sender, but there were already a scheduler for the other core and it is still overloaded. Worse, perhaps all the other cores are able to send messages through to the overloaded process.</div><div><br></div><div>As for the flow control: Erlang systems already employ flow control, namely TCP flow control between distributed nodes. I've seen two recent problems pertaining to having flow control inside flow control: gRPC has 3 layers: gRPC itself, HTTP/2 and TCP. And HTTP/2 has a layer on top of TCP. This is dangerous as the flow control of the underlying system can interfere with the flow control of the system above.</div><div><br></div><div>By extension, any Erlang-mechanism of flow control needs to protect against a scenario where your application has its own layer and make sure it doesn't interfere.</div><div><br></div><div>Personally, I think Ulf Wiger's "Jobs" model paved the way[0]: Apply flow control on input edge of the system, but don't apply it internally. If you do this correct, then a system shouldn't overload because of the border-limit. If you apply internal flow control, you also expose yourself to the danger of an artificial internal bottleneck. Rather, sample internally and use this as a feedback mechanism for the input edge.</div><div><br></div><div>Also note distributed flow control is a considerably harder problem to solve, and since Erlang is distributed by default, any general solution has to address this as well.</div><div><br></div><div>[0] <a href="https://github.com/uwiger/jobs/blob/master/doc/erlang07g-wiger.pdf" target="_blank">https://github.com/uwiger/jobs/blob/master/doc/erlang07g-wiger.pdf</a></div></div><br><div class="gmail_quote"></div><div class="gmail_quote"><div dir="ltr">On Fri, Jan 19, 2018 at 9:51 AM Karl Nilsson <<a href="mailto:kjnilsson@gmail.com" target="_blank">kjnilsson@gmail.com</a>> wrote:<br></div></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">So I saw that the sender punishment was removed in [1]. The commit message doesn't outline any of the reasoning behind this. Is there any more details available about this anywhere I can read? I understand it never really worked that well but it would still be interesting to understand a bit further.<div><br></div><div>On a similar note what is the current thinking on flow control between erlang processes? Are there any improvements on mixing in a few calls in with the casts?<br><div><br></div><div>[1] <a href="https://github.com/erlang/otp/commit/2e601a2efc19d64ed0628a5973596e6331ddcc7c" target="_blank">https://github.com/erlang/otp/commit/2e601a2efc19d64ed0628a5973596e6331ddcc7c</a></div></div></div></blockquote></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
_______________________________________________<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>
</blockquote></div></div></div></div></div>
<br>_______________________________________________<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>
<br></blockquote></div><br></div>
</blockquote></div>