Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 146 lines (112 sloc) 6.755 kb
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
1 = The Philosophy Behind unicorn
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
2
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
3 Being a server that only runs on Unix-like platforms, unicorn is
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
4 strongly tied to the Unix philosophy of doing one thing and (hopefully)
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
5 doing it well. Despite using HTTP, unicorn is strictly a _backend_
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
6 application server for running Rack-based Ruby applications.
7
8 == Avoid Complexity
9
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
10 Instead of attempting to be efficient at serving slow clients, unicorn
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
11 relies on a buffering reverse proxy to efficiently deal with slow
12 clients.
13
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
14 unicorn uses an old-fashioned preforking worker model with blocking I/O.
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
15 Our processing model is the antithesis of more modern (and theoretically
16 more efficient) server processing models using threads or non-blocking
17 I/O with events.
18
19 === Threads and Events Are Hard
20
21 ...to many developers. Reasons for this is beyond the scope of this
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
22 document. unicorn avoids concurrency within each worker process so you
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
23 have fewer things to worry about when developing your application. Of
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
24 course unicorn can use multiple worker processes to utilize multiple
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
25 CPUs or spindles. Applications can still use threads internally, however.
26
27 == Slow Clients Are Problematic
28
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
29 Most benchmarks we've seen don't tell you this, and unicorn doesn't
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
30 care about slow clients... but <i>you</i> should.
31
32 A "slow client" can be any client outside of your datacenter. Network
33 traffic within a local network is always faster than traffic that
34 crosses outside of it. The laws of physics do not allow otherwise.
35
36 Persistent connections were introduced in HTTP/1.1 reduce latency from
37 connection establishment and TCP slow start. They also waste server
38 resources when clients are idle.
39
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
40 Persistent connections mean one of the unicorn worker processes
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
41 (depending on your application, it can be very memory hungry) would
42 spend a significant amount of its time idle keeping the connection alive
43 <i>and not doing anything else</i>. Being single-threaded and using
44 blocking I/O, a worker cannot serve other clients while keeping a
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
45 connection alive. Thus unicorn does not implement persistent
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
46 connections.
47
48 If your application responses are larger than the socket buffer or if
49 you're handling large requests (uploads), worker processes will also be
50 bottlenecked by the speed of the *client* connection. You should
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
51 not allow unicorn to serve clients outside of your local network.
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
52
53 == Application Concurrency != Network Concurrency
54
55 Performance is asymmetric across the different subsystems of the machine
56 and parts of the network. CPUs and main memory can process gigabytes of
57 data in a second; clients on the Internet are usually only capable of a
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
58 tiny fraction of that. unicorn deployments should avoid dealing with
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
59 slow clients directly and instead rely on a reverse proxy to shield it
60 from the effects of slow I/O.
61
62 == Improved Performance Through Reverse Proxying
63
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
64 By acting as a buffer to shield unicorn from slow I/O, a reverse proxy
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
65 will inevitably incur overhead in the form of extra data copies.
66 However, as I/O within a local network is fast (and faster still
12cd717 misc documentation spelling fixes
Eric Wong authored
67 with local sockets), this overhead is negligible for the vast majority
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
68 of HTTP requests and responses.
69
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
70 The ideal reverse proxy complements the weaknesses of unicorn.
71 A reverse proxy for unicorn should meet the following requirements:
72
73 1. It should fully buffer all HTTP requests (and large responses).
74 Each request should be "corked" in the reverse proxy and sent
75 as fast as possible to the backend unicorn processes. This is
76 the most important feature to look for when choosing a
77 reverse proxy for unicorn.
78
79 2. It should spend minimal time in userspace. Network (and disk) I/O
80 are system-level tasks and usually managed by the kernel.
81 This may change if userspace TCP stacks become more popular in the
82 future; but the reverse proxy should not waste time with
83 application-level logic. These concerns should be separated
84
85 3. It should avoid context switches and CPU scheduling overhead.
86 In many (most?) cases, network devices and their interrupts are
87 only be handled by one CPU at a time. It should avoid contention
88 within the system by serializing all network I/O into one (or few)
12cd717 misc documentation spelling fixes
Eric Wong authored
89 userspace processes. Network I/O is not a CPU-intensive task and
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
90 it is not helpful to use multiple CPU cores (at least not for GigE).
91
92 4. It should efficiently manage persistent connections (and
93 pipelining) to slow clients. If you care to serve slow clients
94 outside your network, then these features of HTTP/1.1 will help.
95
96 5. It should (optionally) serve static files. If you have static
97 files on your site (especially large ones), they are far more
98 efficiently served with as few data copies as possible (e.g. with
99 sendfile() to completely avoid copying the data to userspace).
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
100
101 nginx is the only (Free) solution we know of that meets the above
102 requirements.
103
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
104 Indeed, the folks behind unicorn have deployed nginx as a reverse-proxy not
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
105 only for Ruby applications, but also for production applications running
106 Apache/mod_perl, Apache/mod_php and Apache Tomcat. In every single
107 case, performance improved because application servers were able to use
108 backend resources more efficiently and spend less time waiting on slow
109 I/O.
110
111 == Worse Is Better
112
113 Requirements and scope for applications change frequently and
114 drastically. Thus languages like Ruby and frameworks like Rails were
115 built to give developers fewer things to worry about in the face of
116 rapid change.
117
118 On the other hand, stable protocols which host your applications (HTTP
119 and TCP) only change rarely. This is why we recommend you NOT tie your
120 rapidly-changing application logic directly into the processes that deal
121 with the stable outside world. Instead, use HTTP as a common RPC
122 protocol to communicate between your frontend and backend.
123
124 In short: separate your concerns.
125
126 Of course a theoretical "perfect" solution would combine the pieces
127 and _maybe_ give you better performance at the end of the day, but
128 that is not the Unix way.
129
130 == Just Worse in Some Cases
131
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
132 unicorn is not suited for all applications. unicorn is optimized for
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
133 applications that are CPU/memory/disk intensive and spend little time
134 waiting on external resources (e.g. a database server or external API).
135
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
136 unicorn is highly inefficient for Comet/reverse-HTTP/push applications
c0d79db Documentation updates, prep for 0.4.1 release
Eric Wong authored
137 where the HTTP connection spends a large amount of time idle.
138 Nevertheless, the ease of troubleshooting, debugging, and management of
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
139 unicorn may still outweigh the drawbacks for these applications.
7ab6547 PHILOSOPHY: plug the Rainbows! spin-off project
Eric Wong authored
140
141 The {Rainbows!}[http://rainbows.rubyforge.org/] aims to fill the gap for
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
142 odd corner cases where the nginx + unicorn combination is not enough.
536f901 doc: PHILOSOPHY: update Rainbows! section
Eric Wong authored
143 While Rainbows! management/administration is largely identical to
c20077d doc: PHILOSOPHY: formatting fixes
Eric Wong authored
144 unicorn, Rainbows! is far more ambitious and has seen little real-world
536f901 doc: PHILOSOPHY: update Rainbows! section
Eric Wong authored
145 usage.
Something went wrong with that request. Please try again.