145

I would like to know the difference between Nginx and Unicorn. As far as I understand, Nginx is a web server while Unicorn is a Ruby HTTP server.

Since both Nginx and Unicorn can handle HTTP requests, what is the need to use the combination of Nginx and Unicorn for RoR applications?

aaron-coding
  • 2,571
  • 1
  • 23
  • 31
loganathan
  • 5,838
  • 8
  • 33
  • 50
  • 4
    Good question ! I think the title of this question should be, "Why we need the combination of nginx and unicorn. ;) The answers were very helpful for me. – servatj Oct 28 '15 at 17:12
  • 1
    @servatj I've added an answer that explains in greater detail why Unicorn needs a reverse proxy like Nginx in front of it. You might want to check it out ;) – Agis Apr 30 '16 at 19:45

4 Answers4

96

Nginx is a pure web server that's intended for serving up static content and/or redirecting the request to another socket to handle the request.

Unicorn is a Rack web server and only intended to host a 'Rack App' which is usually generating dynamic content. Rack apps can also serve up static content but it's less efficient than most other traditional web servers.

Most RoR setups use a combination of both traditional web servers and Rack servers to apply the best of both of their capabilities. Nginx is incredibly fast at request redirection through proxy balancing and serving up static content. Unicorn is quite capable of processing HTTP headers and balancing inbound requests to Ruby for processing.

Rob Bednark
  • 25,981
  • 23
  • 80
  • 125
Nick
  • 2,393
  • 13
  • 22
89

This answer is complementary to the other ones and explains why Unicorn needs nginx in front of it.

TL;DR The reason that Unicorn is usually deployed together with a reverse proxy like nginx is because its creators deliberately designed it so, making a tradeoff for simplicity.

First of all, there's nothing keeping you from deploying Unicorn without a reverse proxy. However, that wouldn't be a very good idea; let's see why.

Unicorn follows the Unix philosophy which is to do one thing and do it well, and that is to serve fast, low-latency clients (we'll see what this means later on). The fact that Unicorn is designed for fast, low-latency clients also implies that it's not very good with slow, high-latency clients, which is indeed true. This is one of Unicorn's weak points and it's where a reverse proxy comes into play: it sits in front of Unicorn and takes care of those slow clients (we'll see how later on).

Fortunately, such a reverse proxy already exists and is called nginx.

The decision to handle only fast clients, greatly simplifies the design of Unicorn and allows a much simpler and smaller codebase, at the cost of some added complexity on the deployment department (ie. you have to deploy nginx too in addition to Unicorn).

An alternative decision could be designing Unicorn in such a way that it wouldn't need a reverse proxy. However, this means that it would have to implement extra functionality to do all the things that now nginx does, resulting in a more complex codebase and more engineering efforts.

Instead its creators made the decision to leverage existing software that is battle-tested and very well designed and to avoid wasting time and energy on problems already solved by other software.

But let's get technical and answer your question:

Why does Unicorn needs to be deployed together with nginx?

Here are some of the key reasons:

Unicorn uses blocking I/O for clients

Relying on a reverse proxy means that Unicorn doesn't need to use non-blocking I/O. Instead it can use blocking I/O which is inherently simpler and easier for the programmer to follow.

Also as the DESIGN document states:

[Using blocking I/O] allows a simpler code path to be followed within the Ruby interpreter and fewer syscalls.

However, this also has some consequences:

Key point #1: Unicorn is not efficient with slow clients

(For simplicity's sake, we assume a setup with 1 Unicorn worker)

Since blocking I/O is used, a Unicorn worker can only serve one client at a time, so a slow client (ie. one with a slow connection) would effectively keep the worker busy for a longer time (than a fast client would do). In the meantime, the other clients would just wait until the worker is free again (ie. requests would pile up in the queue).

To get around this issue, a reverse proxy is deployed in front of Unicorn, that fully buffers incoming requests and the application responses, and then sends each of them at once (aka spoon-feeds them) to Unicorn and the clients, respectively. In that regard, you could say that the reverse proxy "shields" Unicorn from slow network clients.

Fortunately Nginx is a great candidate for this role, since it is designed to handle thousands of hundreds concurrent clients efficiently.

It's of crucial importance that the reverse proxy should be within the same local network as Unicorn (typically in the same physical machine communicating w/ Unicorn via a Unix domain socket), so that the network latency is kept to a minimum.

So such a proxy effectively plays the role of a fast client that Unicorn is designed to serve in the first place, since it proxies requests to Unicorn fast and keeps the workers busy for the shortest possible amount of time (compared to how much time a client with a slow connection would do).

Key point #2: Unicorn does not support HTTP/1.1 keep-alive

Since Unicorn uses blocking I/O, it also means that it can't support the HTTP/1.1 keep-alive feature, since the persistent connections of slow clients would quickly occupy all the available Unicorn workers.

Therefore to leverage HTTP keep-alive, guess what: a reverse proxy is used.

nginx on the other hand, can handle thousands of concurrent connections using just a few threads. Therefore, it doesn't have the concurrency limits a server like Unicorn has (which essentially limited to the amount of worker processes), which means it can handle persistent connections just fine. More of how this actually works can be found here.

That's why nginx accepts keep-alive connections from the clients and proxies them to Unicorn over plain connections via typically a Unix socket.

Point #3: Unicorn is not very good at serving static files

Again, serving static files is a thing that Unicorn can do but is not designed to do efficiently.

On the otherhand, reverse proxies like nginx though are much more better at it (ie. sendfile(2) & caching).

More

There are other points which are outlined in the PHILOSOPHY document (see "Improved Performance Through Reverse Proxying").

See also some of nginx's basic features.

We see that by leveraging existing software (ie. nginx) and following the Unix philosophy of "doing one thing and do it well", Unicorn is able to follow a simpler design and implementation while maintaining to be efficient at serving Rack apps (eg. your Rails app).

For more information refer to Unicorn's philosophy and design documents which explain in more detail the choices behind Unicorn's design and why nginx is considered a good reverse-proxy for Unicorn.

Agis
  • 32,639
  • 3
  • 73
  • 81
  • But why not just use Nginx I think he was asking, not 'why does unicorn require nginx'. What does Unicorn provide that Nginx does not, for example? – omikes Feb 06 '17 at 21:28
  • 4
    @oMiKeY If that is the case, I believe the other answers adress this question fairly good. I still think my answer provides useful information for anyone trying to understand the _combination_ of nginx & unicorn. – Agis Mar 15 '17 at 16:23
  • 3
    This is pure gold. Thank you! – Magne Nov 22 '17 at 17:14
60

Nginx
enter image description here
Unicorn
enter image description here
Refer to unicorn on github for more information.

Pete - MSFT
  • 4,249
  • 1
  • 21
  • 38
Pratik
  • 11,534
  • 22
  • 69
  • 99
  • 1
    Pratik, What my question is unicorn server can serve both static and dynamic process, then why we are using NGinx or Apache those can process the only static contents, combinely with the passenger or unicorn or mod_php ? – loganathan Jan 05 '12 at 09:20
  • 17
    @loganathan, Both Apache and Nginx are much faster at serving static content than ruby or any of the application servers. They also know how to handle caching and are good at allowing concurrent file downloads while still taking in traffic and passing it to the application servers. – Pratik Jan 05 '12 at 09:28
  • 4
    Also, if you have large amounts of data coming + going, nginx will buffer it from (and spoon feed to) the client. Without nginx, one of your unicorns will be tied up during uploads/downloads. – BraveNewCurrency Jul 22 '13 at 01:34
  • 12
    This does not answer the question why nginx is needed at all. It just puts it in both pictures without any comment. Nick's answer is much better. – gorn Dec 20 '14 at 00:09
  • 1
    I agree with @gorn. This meant nothing to me, for example. – Joshua Grosso Reinstate CMs Nov 16 '15 at 22:08
  • Agree with @gom. Not even the linked Github blog post explains why is nginx needed. See my answer for a detailed explanation: http://stackoverflow.com/questions/8739871/why-does-unicorn-needs-to-be-deployed-together-with-nginx/36954749#36954749 – Agis May 02 '16 at 11:49
  • 1
    Before reading the other answers I wanted to agree that this answer provides no information whatsoever. The best I can make of this diagram is that unicorn used Nginx as a model, rewrote it, and changed some vocabulary words around. Does it really do the same thing? – omikes Feb 06 '17 at 21:22
  • In the bottom picture, is the yellow box supposed to be labeled "unicorn" instead of "nginx"? – mbigras May 12 '17 at 17:32
  • @oMiKeY FYI you can "Flag" this answer as "Not an answer" if you think it doesn't help you. – Agis Oct 20 '17 at 15:00
  • The flagging system on this website is a joke. Useless or stolen answers are no longer moderated when the person giving the answer is well respected in the community. Judging by this persons number of gold medals, flagging this answer would be pointless. Critiquing it in the comments is the last form of criticism allowed on this website, besides downvoting for which I would receive a penalty. – omikes Oct 20 '17 at 18:26
14

Nginx can be used to serve slow clients on a unicorn server as slow clients would choke the unicorn server. Nginx is used as some sort of proxy buffering all requests and responses to slow clients.

See http://unicorn.bogomips.org/

bardiir
  • 14,556
  • 9
  • 41
  • 66