From http://www.erlang.org/doc/man/gen_tcp.html#accept-1:
It is worth noting that the accept call does not have to be issued from the socket owner process. Using version 5.5.3 and higher of the emulator, multiple simultaneous accept calls can be issued from different processes, which allows for a pool of acceptor processes handling incoming connections.
(Q1) Does it mean that we can have Unicorn-style load balancing in Erlang?
(Q2) If so, are there any existing servers or libraries making use of this feature?
(Q3) Unicorn works under the assumption that request processing is fast. Under the same assumption, is it possible to gain better performance by combining acceptors and workers in Erlang?
For those who are not familiar with Unicorn, it is a traditional UNIX prefork web server. Load balancing between worker processes is done by the OS kernel. All workers share a common set of listener sockets and does non-blocking accept() on them. The kernel will decide which worker process to give a socket to and workers will sleep if there is nothing to accept(). For a single listener socket, I believe it's the same when the worker processes do blocking accept() and the OS kernel decides the result of the "race".
I also posted this question in the Erlang Questions mailing list. As pointed out by Daniel Goertzen, there are acceptor pool libraries in Erlang, such as ranch and swarm.
ranch works differently from Unicorn in such a way that it only does "accept" in many processes, and then passes the socket to some worker process.
The way swarm works is the same as Unicorn in the sense that the acceptor and worker is combined. (Thanks to Loïc Hoguin for pointing out) But they are a bit different because swarm can accept a new socket in parallel with the processing of the accepted socket, while Unicorn only accepts after the accepted socket is processed
I prefer the swarm style since it's ideal for both fast and slow requests, while Unicorn requires fast requests.
Instead of attempting to be efficient at serving slow clients, unicorn relies on a buffering reverse proxy to efficiently deal with slow clients.
unicorn is not suited for all applications. unicorn is optimized for applications that are CPU/memory/disk intensive and spend little time waiting on external resources (e.g. a database server or external API).
unicorn is highly inefficient for Comet/reverse-HTTP/push applications where the HTTP connection spends a large amount of time idle.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With