Skip to content

Commit

Permalink
Update documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Eric Wong committed Feb 11, 2009
1 parent a78fdd5 commit 3be825a
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 8 deletions.
134 changes: 127 additions & 7 deletions README
@@ -1,12 +1,121 @@
= Unicorn: UNIX-only fork of Mongrel
= Unicorn: UNIX + LAN/localhost-only fork of Mongrel

Experimental UNIX-only fork of Mongrel. No threads.
Only run this behind a full-HTTP-request-buffering reverse proxy if
you're serving slow clients. That said, nginx is the only reverse
proxy we know of that meets this requirement.

Only run this behind nginx (or another fully-buffering reverse proxy,
I know of none) or to serve clients within the same datacenter. This
is absolutely not designed to deal with slow clients.
== Features

See http://unicorn.bogomips.org for more information.
* process management: Unicorn will reap and restart workers that
die because of broken apps and there is no need to manage
multiple processes yourself.

* doesn't matter if your application is thread-safe or not, workers
all run within their own isolated address space and only serve one
client at a time...

* able to listen on multiple interfaces, including UNIX sockets,
each worker process can also bind to a private port via the
after_fork hook for easy debugging.

* should support all Rack applications (though only Sinatra has been tested)

* nginx-style binary re-execution without losing connections.
You can upgrade unicorn, your entire application, libraries
and even your Ruby interpreter as long as unicorn is
installed in the same path

* before_fork and after_fork hooks in case your application
has special needs when dealing with forked processes. These
can be used to setup signal handlers for logrotation, too.

* Ruby 1.9-compatible (at least the test cases all pass :>)

== Design

* Simplicity: Unicorn is a traditional UNIX prefork web server.
No threads are used at all, this makes applications easier to debug
and fix. When your application goes awry, a BOFH can just
"kill -9" the runaway worker process without worrying about tearing
all clients down, just one. Only UNIX-like systems supporting
fork() and file descriptor inheritance is supported.

* The Ragel->C HTTP parser is taken from Mongrel. This is the
only non-Ruby part and there are no plans to add any more
non-Ruby components.

* All HTTP protocol parsing and I/O is done just like Mongrel:
1. read/parse HTTP request in full
2. call Rack application
3. write HTTP response back to the client

* Like Mongrel, neither keepalive nor pipelining are supported.
These aren't needed since Unicorn is only designed to serve
fast, low-latency clients directly. Do one thing, do it well;
let nginx handle slow clients.

* Configuration is purely in Ruby and eval(). Ruby is less
ambiguous than YAML and lets lambdas for before_fork/after_fork
hooks be defined inline. An optional, separate hot_config_file
may be used to modify supported configuration changes
(and also gives you plenty of rope if you RTFS :>)

* One master process spawns and reaps worker processes. The
Rack application itself is called only within the worker process (but
can be loaded within the master). A copy-on-write friendly garbage
collector like Ruby Enterprise Edition can be used to minimize memory
usage.

* The number of worker processes should be scaled to the number of
CPUs, memory or even spindles you have. If you have an existing
Mongrel cluster, using the same amount of processes should work.
Let a full-HTTP-request-buffering reverse proxy like nginx manage
concurrency to thousands of slow clients for you. Unicorn scaling
should only be concerned about limits of your backend system(s).

* 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().

* Since non-blocking accept() is used, there can be a thundering
herd when an occasional client connects when application
*is not busy*. The thundering herd problem should not affect
applications that are running all the time since worker processes
will only select()/accept() outside of the application dispatch.

* Blocking I/O is used for clients. This allows a simpler code path
to be followed within the Ruby interpreter and fewer syscalls.
Applications that use threads should continue to work if Unicorn
is serving LAN or localhost clients.

* Timeout implementation is done via fchmod(2) in each worker
on a shared file descriptor to update st_ctime on the inode.
Master process wakeups for checking on timeouts is throttled
one a second to minimize the performance impact and simplify
the code path within the worker. Neither futimes(2) nor
pwrite(2)/pread(2) are supported by base MRI, nor are they as
portable on UNIX systems as fchmod(2).

* SIGKILL is used to terminate the timed-out workers as reliably
as possible on a UNIX system.

* The poor performance of select() on large FD sets is avoided
as few file descriptors are used in each worker.
There should be no gain from moving to highly scalable but
unportable event notification solutions for watching few
file descriptors.

* Since workers only work on one client at a time, the temporary
file for storing large POST/PUT requests is reused for the
lifetime of the process. This should limit temp directory
growth on UNIX filesystems where temp file names are never
purged from the containing directory.

* If the master process dies unexpectedly for any reason,
workers will notice within :timeout/2 seconds and follow
the master to its death.

== License

Expand All @@ -24,10 +133,21 @@ least a friend who can build it for you.

Finally, the source includes a setup.rb for those who hate RubyGems.

You can get the source via git via the following locations:

git://git.bogomips.org/unicorn.git

http://git.bogomips.org/unicorn.git

== Usage

See the Sinatra example.

It should be capable of running all Rack applications. Since this
is a preforking webserver

== Contact

Newsgroup and mailing list coming, or it'll be a part of the Mongrel project.
Newsgroup and mailing list coming, or it'll be a part of the Mongrel project...

Email Eric Wong at normalperson@yhbt.net for now.
7 changes: 6 additions & 1 deletion TODO
@@ -1,4 +1,9 @@
X process management tests
tests for process management
tests for signal handling
tests for hot_config_file reloading
tests for binary rexecution + socket inheritance
tests for upload tempfile reuse
tests for timeouts
X Rack compat
Timestamped logger
QA behaviour on 1.9
Expand Down

0 comments on commit 3be825a

Please sign in to comment.