unicorn 3.6.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +1 -0
- data/.manifest +13 -0
- data/ChangeLog +783 -1
- data/DESIGN +0 -8
- data/Documentation/GNUmakefile +1 -1
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +2 -2
- data/HACKING +11 -0
- data/KNOWN_ISSUES +2 -2
- data/LATEST +24 -24
- data/Links +53 -0
- data/NEWS +66 -0
- data/PHILOSOPHY +49 -49
- data/Sandbox +13 -4
- data/TODO +0 -2
- data/TUNING +31 -9
- data/bin/unicorn +2 -1
- data/bin/unicorn_rails +2 -1
- data/examples/big_app_gc.rb +2 -33
- data/examples/nginx.conf +17 -4
- data/ext/unicorn_http/ext_help.h +16 -0
- data/ext/unicorn_http/extconf.rb +1 -0
- data/ext/unicorn_http/global_variables.h +9 -3
- data/ext/unicorn_http/unicorn_http.c +357 -259
- data/ext/unicorn_http/unicorn_http.rl +148 -50
- data/lib/unicorn/configurator.rb +36 -8
- data/lib/unicorn/const.rb +5 -3
- data/lib/unicorn/http_request.rb +1 -3
- data/lib/unicorn/http_server.rb +82 -95
- data/lib/unicorn/oob_gc.rb +61 -50
- data/lib/unicorn/socket_helper.rb +23 -8
- data/lib/unicorn/worker.rb +45 -4
- data/lib/unicorn.rb +8 -6
- data/script/isolate_for_tests +4 -2
- data/t/broken-app.ru +12 -0
- data/t/heartbeat-timeout.ru +12 -0
- data/t/oob_gc.ru +21 -0
- data/t/oob_gc_path.ru +21 -0
- data/t/t0001-reload-bad-config.sh +1 -0
- data/t/t0002-parser-error.sh +64 -1
- data/t/t0004-heartbeat-timeout.sh +69 -0
- data/t/t0009-broken-app.sh +56 -0
- data/t/t0019-max_header_len.sh +49 -0
- data/t/t0020-at_exit-handler.sh +49 -0
- data/t/t9001-oob_gc.sh +47 -0
- data/t/t9002-oob_gc-path.sh +75 -0
- data/test/benchmark/stack.ru +8 -0
- data/test/unit/test_droplet.rb +28 -0
- data/test/unit/test_http_parser.rb +60 -4
- data/test/unit/test_http_parser_ng.rb +54 -0
- data/test/unit/test_response.rb +1 -1
- data/test/unit/test_server.rb +1 -1
- data/test/unit/test_signals.rb +1 -1
- data/test/unit/test_socket_helper.rb +8 -0
- data/test/unit/test_upload.rb +1 -1
- data/unicorn.gemspec +3 -2
- metadata +44 -16
data/DESIGN
CHANGED
@@ -76,14 +76,6 @@
|
|
76
76
|
Applications that use threads continue to work if Unicorn
|
77
77
|
is only serving LAN or localhost clients.
|
78
78
|
|
79
|
-
* Timeout implementation is done via fchmod(2) in each worker
|
80
|
-
on a shared file descriptor to update st_ctime on the inode.
|
81
|
-
Master process wakeups for checking on timeouts is throttled
|
82
|
-
one a second to minimize the performance impact and simplify
|
83
|
-
the code path within the worker. Neither futimes(2) nor
|
84
|
-
pwrite(2)/pread(2) are supported by base MRI, nor are they as
|
85
|
-
portable on UNIX systems as fchmod(2).
|
86
|
-
|
87
79
|
* SIGKILL is used to terminate the timed-out workers from misbehaving apps
|
88
80
|
as reliably as possible on a UNIX system. The default timeout is a
|
89
81
|
generous 60 seconds (same default as in Mongrel).
|
data/Documentation/GNUmakefile
CHANGED
data/GIT-VERSION-FILE
CHANGED
@@ -1 +1 @@
|
|
1
|
-
GIT_VERSION =
|
1
|
+
GIT_VERSION = 4.0.0
|
data/GIT-VERSION-GEN
CHANGED
data/GNUmakefile
CHANGED
@@ -164,7 +164,7 @@ pkg_extra := GIT-VERSION-FILE ChangeLog LATEST NEWS \
|
|
164
164
|
ChangeLog: GIT-VERSION-FILE .wrongdoc.yml
|
165
165
|
wrongdoc prepare
|
166
166
|
|
167
|
-
.manifest: ChangeLog $(ext)/unicorn_http.c
|
167
|
+
.manifest: ChangeLog $(ext)/unicorn_http.c man
|
168
168
|
(git ls-files && for i in $@ $(pkg_extra); do echo $$i; done) | \
|
169
169
|
LC_ALL=C sort > $@+
|
170
170
|
cmp $@+ $@ || mv $@+ $@
|
@@ -176,7 +176,7 @@ doc: .document $(ext)/unicorn_http.c man html .wrongdoc.yml
|
|
176
176
|
$(RM) -r doc
|
177
177
|
wrongdoc all
|
178
178
|
install -m644 COPYING doc/COPYING
|
179
|
-
install -m644 $(shell grep '^[A-Z]' .document) doc/
|
179
|
+
install -m644 $(shell LC_ALL=C grep '^[A-Z]' .document) doc/
|
180
180
|
install -m644 $(man1_paths) doc/
|
181
181
|
tar cf - $$(git ls-files examples/) | (cd doc && tar xf -)
|
182
182
|
$(RM) $(man1_rdoc)
|
data/HACKING
CHANGED
@@ -107,6 +107,17 @@ git itself. See the Documentation/SubmittingPatches document
|
|
107
107
|
distributed with git on on patch submission guidelines to follow. Just
|
108
108
|
don't email the git mailing list or maintainer with Unicorn patches :)
|
109
109
|
|
110
|
+
== Building a Gem
|
111
|
+
|
112
|
+
In order to build the gem, you must install the following components:
|
113
|
+
|
114
|
+
* wrongdoc
|
115
|
+
* pandoc
|
116
|
+
|
117
|
+
You can build the Unicorn gem with the following command:
|
118
|
+
|
119
|
+
gmake gem
|
120
|
+
|
110
121
|
== Running Development Versions
|
111
122
|
|
112
123
|
It is easy to install the contents of your git working directory:
|
data/KNOWN_ISSUES
CHANGED
@@ -5,13 +5,13 @@ acceptable solution. Those issues are documented here.
|
|
5
5
|
|
6
6
|
* PRNGs (pseudo-random number generators) loaded before forking
|
7
7
|
(e.g. "preload_app true") may need to have their internal state
|
8
|
-
reset in the after_fork hook. Starting with \Unicorn 3.6.
|
8
|
+
reset in the after_fork hook. Starting with \Unicorn 3.6.1, we
|
9
9
|
have builtin workarounds for Kernel#rand and OpenSSL::Random users,
|
10
10
|
but applications may use other PRNGs.
|
11
11
|
|
12
12
|
* Under some versions of Ruby 1.8, it is necessary to call +srand+ in an
|
13
13
|
after_fork hook to get correct random number generation. We have a builtin
|
14
|
-
workaround for this starting with \Unicorn 3.6.
|
14
|
+
workaround for this starting with \Unicorn 3.6.1
|
15
15
|
|
16
16
|
See http://redmine.ruby-lang.org/issues/show/4338
|
17
17
|
|
data/LATEST
CHANGED
@@ -1,32 +1,32 @@
|
|
1
|
-
=== unicorn
|
1
|
+
=== unicorn 4.0.0 - for mythical hardware! / 2011-06-27 09:05 UTC
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
A single Unicorn instance may manage more than 1024 workers
|
4
|
+
without needing privileges to modify resource limits. As a
|
5
|
+
result of this, the "raindrops"[1] gem/library is now a required
|
6
|
+
dependency.
|
6
7
|
|
7
|
-
|
8
|
+
TCP socket defaults now favor low latency to mimic UNIX domain
|
9
|
+
socket behavior (tcp_nodelay: true, tcp_nopush: false). This
|
10
|
+
hurts throughput, users who want to favor throughput should
|
11
|
+
specify "tcp_nodelay: false, tcp_nopush: true" in the listen
|
12
|
+
directive.
|
8
13
|
|
9
|
-
|
10
|
-
|
14
|
+
Error logging is more consistent and all lines should be
|
15
|
+
formatted correctly in backtraces. This may break the
|
16
|
+
behavior of some log parsers.
|
11
17
|
|
12
|
-
|
13
|
-
|
18
|
+
The call stack is smaller and thus easier to examine backtraces
|
19
|
+
when debugging Rack applications.
|
14
20
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
21
|
+
There are some internal API changes and cleanups, but none that
|
22
|
+
affect applications designed for Rack. See "git log v3.7.0.."
|
23
|
+
for details.
|
19
24
|
|
20
|
-
|
25
|
+
For users who cannot install kgio[2] or raindrops, Unicorn 1.1.x
|
26
|
+
remains supported indefinitely. Unicorn 3.x will remain
|
27
|
+
supported if there is demand. We expect raindrops to introduce
|
28
|
+
fewer portability problems than kgio did, however.
|
21
29
|
|
22
|
-
|
23
|
-
|
24
|
-
make configuration easier especially since the "working_directory"
|
25
|
-
configurator directive exists. Brought up by Matthew Kocher:
|
26
|
-
http://thread.gmane.org/gmane.comp.lang.ruby.unicorn.general/900
|
27
|
-
|
28
|
-
* workers will just die (and restart) if log reopening fails for
|
29
|
-
any reason (including user error). This is to workaround the issue
|
30
|
-
reported by Emmanuel Gomez:
|
31
|
-
http://thread.gmane.org/gmane.comp.lang.ruby.unicorn.general/906
|
30
|
+
[1] http://raindrops.bogomips.org/
|
31
|
+
[2] http://bogomips.org/kgio/
|
32
32
|
|
data/Links
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
= Related Projects
|
2
|
+
|
3
|
+
If you're interested in \Unicorn, you may be interested in some of the projects
|
4
|
+
listed below. If you have any links to add/change/remove, please tell us at
|
5
|
+
mailto:mongrel-unicorn@rubyforge.org!
|
6
|
+
|
7
|
+
== Disclaimer
|
8
|
+
|
9
|
+
The \Unicorn project is not responsible for the content in these links.
|
10
|
+
Furthermore, the \Unicorn project has never, does not and will never endorse:
|
11
|
+
|
12
|
+
* any for-profit entities or services
|
13
|
+
* any non-{Free Software}[http://www.gnu.org/philosophy/free-sw.html]
|
14
|
+
|
15
|
+
The existence of these links does not imply endorsement of any entities
|
16
|
+
or services behind them.
|
17
|
+
|
18
|
+
=== For use with \Unicorn
|
19
|
+
|
20
|
+
* {Bluepill}[https://github.com/arya/bluepill] -
|
21
|
+
a simple process monitoring tool written in Ruby
|
22
|
+
|
23
|
+
* {golden_brindle}[https://github.com/simonoff/golden_brindle] - tool to
|
24
|
+
manage multiple \Unicorn instances/applications on a single server
|
25
|
+
|
26
|
+
* {raindrops}[http://raindrops.bogomips.org/] - real-time stats for
|
27
|
+
preforking Rack servers
|
28
|
+
|
29
|
+
=== \Unicorn is written to work with
|
30
|
+
|
31
|
+
* {Rack}[http://rack.rubyforge.org/] - a minimal interface between webservers
|
32
|
+
supporting Ruby and Ruby frameworks
|
33
|
+
|
34
|
+
* {Ruby}[http://ruby-lang.org/] - the programming language of Rack and \Unicorn
|
35
|
+
|
36
|
+
* {nginx}[http://nginx.org/] - the reverse proxy for use with \Unicorn
|
37
|
+
|
38
|
+
* {kgio}[http://bogomips.org/kgio/] - the I/O library written for \Unicorn
|
39
|
+
|
40
|
+
=== Derivatives
|
41
|
+
|
42
|
+
* {Green Unicorn}[http://gunicorn.org/] - a Python version of \Unicorn
|
43
|
+
|
44
|
+
* {Rainbows!}[http://rainbows.rubyforge.org/] - \Unicorn for sleepy
|
45
|
+
apps and slow clients.
|
46
|
+
|
47
|
+
=== Prior Work
|
48
|
+
|
49
|
+
* {Mongrel}[http://mongrel.rubyforge.org/] - the awesome webserver \Unicorn is
|
50
|
+
based on
|
51
|
+
|
52
|
+
* {david}[http://bogomips.org/david.git] - a tool to explain why you need
|
53
|
+
nginx in front of \Unicorn
|
data/NEWS
CHANGED
@@ -1,3 +1,69 @@
|
|
1
|
+
=== unicorn 4.0.0 - for mythical hardware! / 2011-06-27 09:05 UTC
|
2
|
+
|
3
|
+
A single Unicorn instance may manage more than 1024 workers
|
4
|
+
without needing privileges to modify resource limits. As a
|
5
|
+
result of this, the "raindrops"[1] gem/library is now a required
|
6
|
+
dependency.
|
7
|
+
|
8
|
+
TCP socket defaults now favor low latency to mimic UNIX domain
|
9
|
+
socket behavior (tcp_nodelay: true, tcp_nopush: false). This
|
10
|
+
hurts throughput, users who want to favor throughput should
|
11
|
+
specify "tcp_nodelay: false, tcp_nopush: true" in the listen
|
12
|
+
directive.
|
13
|
+
|
14
|
+
Error logging is more consistent and all lines should be
|
15
|
+
formatted correctly in backtraces. This may break the
|
16
|
+
behavior of some log parsers.
|
17
|
+
|
18
|
+
The call stack is smaller and thus easier to examine backtraces
|
19
|
+
when debugging Rack applications.
|
20
|
+
|
21
|
+
There are some internal API changes and cleanups, but none that
|
22
|
+
affect applications designed for Rack. See "git log v3.7.0.."
|
23
|
+
for details.
|
24
|
+
|
25
|
+
For users who cannot install kgio[2] or raindrops, Unicorn 1.1.x
|
26
|
+
remains supported indefinitely. Unicorn 3.x will remain
|
27
|
+
supported if there is demand. We expect raindrops to introduce
|
28
|
+
fewer portability problems than kgio did, however.
|
29
|
+
|
30
|
+
[1] http://raindrops.bogomips.org/
|
31
|
+
[2] http://bogomips.org/kgio/
|
32
|
+
|
33
|
+
=== unicorn 3.7.0 - minor feature update / 2011-06-09 20:51 UTC
|
34
|
+
|
35
|
+
* miscellaneous documentation improvements
|
36
|
+
* return 414 (instead of 400) for Request-URI Too Long
|
37
|
+
* strip leading and trailing linear whitespace in header values
|
38
|
+
|
39
|
+
User-visible improvements meant for Rainbows! users:
|
40
|
+
|
41
|
+
* add :ipv6only "listen" option (same as nginx)
|
42
|
+
|
43
|
+
=== unicorn 3.6.2 - fix Unicorn::OobGC module / 2011-04-30 06:40 UTC
|
44
|
+
|
45
|
+
The optional Unicorn::OobGC module is reimplemented to fix
|
46
|
+
breakage that appeared in v3.3.1. There are also minor
|
47
|
+
documentation updates, but no code changes as of 3.6.1 for
|
48
|
+
non-OobGC users.
|
49
|
+
|
50
|
+
There is also a v1.1.7 release to fix the same OobGC breakage
|
51
|
+
that appeared for 1.1.x users in the v1.1.6 release.
|
52
|
+
|
53
|
+
=== unicorn 1.1.7 - major fixes to minor components / 2011-04-30 06:33 UTC
|
54
|
+
|
55
|
+
No changes to the core code, so this release only affects users
|
56
|
+
of the Unicorn::OobGC and Unicorn::ExecCGI modules.
|
57
|
+
Unicorn::OobGC was totally broken by the fix in the v1.1.6
|
58
|
+
release and is now reimplemented. Unicorn::ExecCGI (which
|
59
|
+
hardly anybody uses) now returns proper HTTP status codes.
|
60
|
+
|
61
|
+
=== unicorn 3.6.1 - fix OpenSSL PRNG workaround / 2011-04-26 23:06 UTC
|
62
|
+
|
63
|
+
Our attempt in 3.6.0 to workaround a problem with the OpenSSL
|
64
|
+
PRNG actually made the problem worse. This release corrects the
|
65
|
+
workaround to properly reseed the OpenSSL PRNG after forking.
|
66
|
+
|
1
67
|
=== unicorn 3.6.0 - small fixes, PRNG workarounds / 2011-04-21 06:46 UTC
|
2
68
|
|
3
69
|
Mainly small fixes, improvements, and workarounds for fork() issues
|
data/PHILOSOPHY
CHANGED
@@ -1,17 +1,17 @@
|
|
1
|
-
= The Philosophy Behind
|
1
|
+
= The Philosophy Behind unicorn
|
2
2
|
|
3
|
-
Being a server that only runs on Unix-like platforms,
|
3
|
+
Being a server that only runs on Unix-like platforms, unicorn is
|
4
4
|
strongly tied to the Unix philosophy of doing one thing and (hopefully)
|
5
|
-
doing it well. Despite using HTTP,
|
5
|
+
doing it well. Despite using HTTP, unicorn is strictly a _backend_
|
6
6
|
application server for running Rack-based Ruby applications.
|
7
7
|
|
8
8
|
== Avoid Complexity
|
9
9
|
|
10
|
-
Instead of attempting to be efficient at serving slow clients,
|
10
|
+
Instead of attempting to be efficient at serving slow clients, unicorn
|
11
11
|
relies on a buffering reverse proxy to efficiently deal with slow
|
12
12
|
clients.
|
13
13
|
|
14
|
-
|
14
|
+
unicorn uses an old-fashioned preforking worker model with blocking I/O.
|
15
15
|
Our processing model is the antithesis of more modern (and theoretically
|
16
16
|
more efficient) server processing models using threads or non-blocking
|
17
17
|
I/O with events.
|
@@ -19,14 +19,14 @@ I/O with events.
|
|
19
19
|
=== Threads and Events Are Hard
|
20
20
|
|
21
21
|
...to many developers. Reasons for this is beyond the scope of this
|
22
|
-
document.
|
22
|
+
document. unicorn avoids concurrency within each worker process so you
|
23
23
|
have fewer things to worry about when developing your application. Of
|
24
|
-
course
|
24
|
+
course unicorn can use multiple worker processes to utilize multiple
|
25
25
|
CPUs or spindles. Applications can still use threads internally, however.
|
26
26
|
|
27
27
|
== Slow Clients Are Problematic
|
28
28
|
|
29
|
-
Most benchmarks we've seen don't tell you this, and
|
29
|
+
Most benchmarks we've seen don't tell you this, and unicorn doesn't
|
30
30
|
care about slow clients... but <i>you</i> should.
|
31
31
|
|
32
32
|
A "slow client" can be any client outside of your datacenter. Network
|
@@ -37,71 +37,71 @@ Persistent connections were introduced in HTTP/1.1 reduce latency from
|
|
37
37
|
connection establishment and TCP slow start. They also waste server
|
38
38
|
resources when clients are idle.
|
39
39
|
|
40
|
-
Persistent connections mean one of the
|
40
|
+
Persistent connections mean one of the unicorn worker processes
|
41
41
|
(depending on your application, it can be very memory hungry) would
|
42
42
|
spend a significant amount of its time idle keeping the connection alive
|
43
43
|
<i>and not doing anything else</i>. Being single-threaded and using
|
44
44
|
blocking I/O, a worker cannot serve other clients while keeping a
|
45
|
-
connection alive. Thus
|
45
|
+
connection alive. Thus unicorn does not implement persistent
|
46
46
|
connections.
|
47
47
|
|
48
48
|
If your application responses are larger than the socket buffer or if
|
49
49
|
you're handling large requests (uploads), worker processes will also be
|
50
50
|
bottlenecked by the speed of the *client* connection. You should
|
51
|
-
not allow
|
51
|
+
not allow unicorn to serve clients outside of your local network.
|
52
52
|
|
53
53
|
== Application Concurrency != Network Concurrency
|
54
54
|
|
55
55
|
Performance is asymmetric across the different subsystems of the machine
|
56
56
|
and parts of the network. CPUs and main memory can process gigabytes of
|
57
57
|
data in a second; clients on the Internet are usually only capable of a
|
58
|
-
tiny fraction of that.
|
58
|
+
tiny fraction of that. unicorn deployments should avoid dealing with
|
59
59
|
slow clients directly and instead rely on a reverse proxy to shield it
|
60
60
|
from the effects of slow I/O.
|
61
61
|
|
62
62
|
== Improved Performance Through Reverse Proxying
|
63
63
|
|
64
|
-
By acting as a buffer to shield
|
64
|
+
By acting as a buffer to shield unicorn from slow I/O, a reverse proxy
|
65
65
|
will inevitably incur overhead in the form of extra data copies.
|
66
66
|
However, as I/O within a local network is fast (and faster still
|
67
67
|
with local sockets), this overhead is neglible for the vast majority
|
68
68
|
of HTTP requests and responses.
|
69
69
|
|
70
|
-
The ideal reverse proxy complements the weaknesses of
|
71
|
-
A reverse proxy for
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
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)
|
89
|
+
userspace procceses. Network I/O is not a CPU-intensive task and
|
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).
|
100
100
|
|
101
101
|
nginx is the only (Free) solution we know of that meets the above
|
102
102
|
requirements.
|
103
103
|
|
104
|
-
Indeed, the folks behind
|
104
|
+
Indeed, the folks behind unicorn have deployed nginx as a reverse-proxy not
|
105
105
|
only for Ruby applications, but also for production applications running
|
106
106
|
Apache/mod_perl, Apache/mod_php and Apache Tomcat. In every single
|
107
107
|
case, performance improved because application servers were able to use
|
@@ -129,17 +129,17 @@ that is not the Unix way.
|
|
129
129
|
|
130
130
|
== Just Worse in Some Cases
|
131
131
|
|
132
|
-
|
132
|
+
unicorn is not suited for all applications. unicorn is optimized for
|
133
133
|
applications that are CPU/memory/disk intensive and spend little time
|
134
134
|
waiting on external resources (e.g. a database server or external API).
|
135
135
|
|
136
|
-
|
136
|
+
unicorn is highly inefficient for Comet/reverse-HTTP/push applications
|
137
137
|
where the HTTP connection spends a large amount of time idle.
|
138
138
|
Nevertheless, the ease of troubleshooting, debugging, and management of
|
139
|
-
|
139
|
+
unicorn may still outweigh the drawbacks for these applications.
|
140
140
|
|
141
141
|
The {Rainbows!}[http://rainbows.rubyforge.org/] aims to fill the gap for
|
142
|
-
odd corner cases where the nginx +
|
142
|
+
odd corner cases where the nginx + unicorn combination is not enough.
|
143
143
|
While Rainbows! management/administration is largely identical to
|
144
|
-
|
144
|
+
unicorn, Rainbows! is far more ambitious and has seen little real-world
|
145
145
|
usage.
|
data/Sandbox
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
Since unicorn includes executables and is usually used to start a Ruby
|
4
4
|
process, there are certain caveats to using it with tools that sandbox
|
5
5
|
RubyGems installations such as
|
6
|
-
{Bundler}[http://
|
6
|
+
{Bundler}[http://gembundler.com/] or
|
7
7
|
{Isolate}[http://github.com/jbarnette/isolate].
|
8
8
|
|
9
9
|
== General deployment
|
@@ -45,11 +45,20 @@ This is no longer be an issue as of bundler 0.9.17
|
|
45
45
|
|
46
46
|
ref: http://mid.gmane.org/8FC34B23-5994-41CC-B5AF-7198EF06909E@tramchase.com
|
47
47
|
|
48
|
+
=== BUNDLE_GEMFILE for Capistrano users
|
49
|
+
|
50
|
+
You may need to set or reset the BUNDLE_GEMFILE environment variable in
|
51
|
+
the before_exec hook:
|
52
|
+
|
53
|
+
before_exec do |server|
|
54
|
+
ENV["BUNDLE_GEMFILE"] = "/path/to/app/current/Gemfile"
|
55
|
+
end
|
56
|
+
|
48
57
|
=== Other ENV pollution issues
|
49
58
|
|
50
|
-
|
51
|
-
|
52
|
-
http://gist.github.com/534668
|
59
|
+
If you're using an older Bundler version (0.9.x), you may need to set or
|
60
|
+
reset GEM_HOME, GEM_PATH and PATH environment variables in the
|
61
|
+
before_exec hook as illustrated by http://gist.github.com/534668
|
53
62
|
|
54
63
|
== Isolate
|
55
64
|
|
data/TODO
CHANGED
data/TUNING
CHANGED
@@ -1,12 +1,34 @@
|
|
1
|
-
= Tuning Unicorn
|
1
|
+
= Tuning \Unicorn
|
2
2
|
|
3
|
-
Unicorn performance is generally as good as a (mostly) Ruby web server
|
3
|
+
\Unicorn performance is generally as good as a (mostly) Ruby web server
|
4
4
|
can provide. Most often the performance bottleneck is in the web
|
5
5
|
application running on Unicorn rather than Unicorn itself.
|
6
6
|
|
7
|
-
== Unicorn Configuration
|
7
|
+
== \Unicorn Configuration
|
8
8
|
|
9
9
|
See Unicorn::Configurator for details on the config file format.
|
10
|
+
+worker_processes+ is the most-commonly needed tuning parameter.
|
11
|
+
|
12
|
+
=== Unicorn::Configurator#worker_processes
|
13
|
+
|
14
|
+
* worker_processes should be scaled to the number of processes your
|
15
|
+
backend system(s) can support. DO NOT scale it to the number of
|
16
|
+
external network clients your application expects to be serving.
|
17
|
+
\Unicorn is NOT for serving slow clients, that is the job of nginx.
|
18
|
+
|
19
|
+
* worker_processes should be *at* *least* the number of CPU cores on
|
20
|
+
a dedicated server. If your application has occasionally slow
|
21
|
+
responses that are /not/ CPU-intensive, you may increase this to
|
22
|
+
workaround those inefficiencies.
|
23
|
+
|
24
|
+
* worker_processes may be increased for Unicorn::OobGC users to provide
|
25
|
+
more consistent response times.
|
26
|
+
|
27
|
+
* Never, ever, increase worker_processes to the point where the system
|
28
|
+
runs out of physical memory and hits swap. Production servers should
|
29
|
+
never see heavy swap activity.
|
30
|
+
|
31
|
+
=== Unicorn::Configurator#listen Options
|
10
32
|
|
11
33
|
* Setting a very low value for the :backlog parameter in "listen"
|
12
34
|
directives can allow failover to happen more quickly if your
|
@@ -30,6 +52,11 @@ See Unicorn::Configurator for details on the config file format.
|
|
30
52
|
and may also thrash CPU caches, cancelling out performance gains
|
31
53
|
one would normally expect.
|
32
54
|
|
55
|
+
* UNIX domain sockets are slighly faster than TCP sockets, but only
|
56
|
+
work if nginx is on the same machine.
|
57
|
+
|
58
|
+
== Other \Unicorn settings
|
59
|
+
|
33
60
|
* Setting "preload_app true" can allow copy-on-write-friendly GC to
|
34
61
|
be used to save memory. It will probably not work out of the box with
|
35
62
|
applications that open sockets or perform random I/O on files.
|
@@ -40,12 +67,7 @@ See Unicorn::Configurator for details on the config file format.
|
|
40
67
|
* On POSIX-compliant filesystems, it is safe for multiple threads or
|
41
68
|
processes to append to one log file as long as all the processes are
|
42
69
|
have them unbuffered (File#sync = true) or they are
|
43
|
-
record(line)-buffered in userspace.
|
44
|
-
|
45
|
-
* worker_processes should be scaled to the number of processes your
|
46
|
-
backend system(s) can support. DO NOT scale it to the number of
|
47
|
-
external network clients your application expects to be serving.
|
48
|
-
Unicorn is NOT for serving slow clients, that is the job of nginx.
|
70
|
+
record(line)-buffered in userspace before any writes.
|
49
71
|
|
50
72
|
== Kernel Parameters (Linux sysctl)
|
51
73
|
|
data/bin/unicorn
CHANGED
@@ -106,6 +106,7 @@ op = OptionParser.new("", 24, ' ') do |opts|
|
|
106
106
|
end
|
107
107
|
|
108
108
|
app = Unicorn.builder(ARGV[0] || 'config.ru', op)
|
109
|
+
op = nil
|
109
110
|
|
110
111
|
if $DEBUG
|
111
112
|
require 'pp'
|
@@ -117,4 +118,4 @@ if $DEBUG
|
|
117
118
|
end
|
118
119
|
|
119
120
|
Unicorn::Launcher.daemonize!(options) if rackup_opts[:daemonize]
|
120
|
-
Unicorn.
|
121
|
+
Unicorn::HttpServer.new(app, options).start.join
|
data/bin/unicorn_rails
CHANGED
@@ -186,6 +186,7 @@ def rails_builder(ru, op, daemonize)
|
|
186
186
|
end
|
187
187
|
|
188
188
|
app = rails_builder(ARGV[0], op, rackup_opts[:daemonize])
|
189
|
+
op = nil
|
189
190
|
|
190
191
|
if $DEBUG
|
191
192
|
require 'pp'
|
@@ -205,4 +206,4 @@ if rackup_opts[:daemonize]
|
|
205
206
|
options[:pid] = "tmp/pids/unicorn.pid"
|
206
207
|
Unicorn::Launcher.daemonize!(options)
|
207
208
|
end
|
208
|
-
Unicorn.
|
209
|
+
Unicorn::HttpServer.new(app, options).start.join
|
data/examples/big_app_gc.rb
CHANGED
@@ -1,33 +1,2 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
# You could customize this patch to read REQ["PATH_INFO"] and only
|
4
|
-
# call GC.start after expensive requests.
|
5
|
-
#
|
6
|
-
# We could have this wrap the response body.close as middleware, but the
|
7
|
-
# scannable stack is would still be bigger than it would be here.
|
8
|
-
#
|
9
|
-
# This shouldn't hurt overall performance as long as the server cluster
|
10
|
-
# is at <=50% CPU capacity, and improves the performance of most memory
|
11
|
-
# intensive requests. This serves to improve _client-visible_
|
12
|
-
# performance (possibly at the cost of overall performance).
|
13
|
-
#
|
14
|
-
# We'll call GC after each request is been written out to the socket, so
|
15
|
-
# the client never sees the extra GC hit it. It's ideal to call the GC
|
16
|
-
# inside the HTTP server (vs middleware or hooks) since the stack is
|
17
|
-
# smaller at this point, so the GC will both be faster and more
|
18
|
-
# effective at releasing unused memory.
|
19
|
-
#
|
20
|
-
# This monkey patch is _only_ effective for applications that use a lot
|
21
|
-
# of memory, and will hurt simpler apps/endpoints that can process
|
22
|
-
# multiple requests before incurring GC.
|
23
|
-
|
24
|
-
class Unicorn::HttpServer
|
25
|
-
REQ = Unicorn::HttpRequest::REQ
|
26
|
-
alias _process_client process_client
|
27
|
-
undef_method :process_client
|
28
|
-
def process_client(client)
|
29
|
-
_process_client(client)
|
30
|
-
REQ.clear
|
31
|
-
GC.start
|
32
|
-
end
|
33
|
-
end if defined?(Unicorn)
|
1
|
+
# see {Unicorn::OobGC}[http://unicorn.bogomips.org/Unicorn/OobGC.html]
|
2
|
+
# Unicorn::OobGC was broken in Unicorn v3.3.1 - v3.6.1 and fixed in v3.6.2
|
data/examples/nginx.conf
CHANGED
@@ -87,6 +87,14 @@ http {
|
|
87
87
|
# listen 80 default deferred; # for Linux
|
88
88
|
# listen 80 default accept_filter=httpready; # for FreeBSD
|
89
89
|
|
90
|
+
# If you have IPv6, you'll likely want to have two separate listeners.
|
91
|
+
# One on IPv4 only (the default), and another on IPv6 only instead
|
92
|
+
# of a single dual-stack listener. A dual-stack listener will make
|
93
|
+
# for ugly IPv4 addresses in $remote_addr (e.g ":ffff:10.0.0.1"
|
94
|
+
# instead of just "10.0.0.1") and potentially trigger bugs in
|
95
|
+
# some software.
|
96
|
+
# listen [::]:80 ipv6only=on; # deferred or accept_filter recommended
|
97
|
+
|
90
98
|
client_max_body_size 4G;
|
91
99
|
server_name _;
|
92
100
|
|
@@ -125,10 +133,15 @@ http {
|
|
125
133
|
proxy_redirect off;
|
126
134
|
|
127
135
|
# set "proxy_buffering off" *only* for Rainbows! when doing
|
128
|
-
# Comet/long-poll
|
129
|
-
#
|
130
|
-
#
|
131
|
-
# clients,
|
136
|
+
# Comet/long-poll/streaming. It's also safe to set if you're using
|
137
|
+
# only serving fast clients with Unicorn + nginx, but not slow
|
138
|
+
# clients. You normally want nginx to buffer responses to slow
|
139
|
+
# clients, even with Rails 3.1 streaming because otherwise a slow
|
140
|
+
# client can become a bottleneck of Unicorn.
|
141
|
+
#
|
142
|
+
# The Rack application may also set "X-Accel-Buffering (yes|no)"
|
143
|
+
# in the response headers do disable/enable buffering on a
|
144
|
+
# per-response basis.
|
132
145
|
# proxy_buffering off;
|
133
146
|
|
134
147
|
proxy_pass http://app_server;
|