about summary refs log tree commit homepage
path: root/README
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-02-11 14:21:20 -0800
committerEric Wong <normalperson@yhbt.net>2009-02-11 14:21:20 -0800
commit3be825a50f0d9f7aa443e277a1b6c6bb667c1fb1 (patch)
tree1d6e9b77582fec873ac0f6b217093b0dfb2c9e50 /README
parenta78fdd5361f8e4e27eae893aedb21a0256c12a88 (diff)
downloadunicorn-3be825a50f0d9f7aa443e277a1b6c6bb667c1fb1.tar.gz
Diffstat (limited to 'README')
-rw-r--r--README134
1 files changed, 127 insertions, 7 deletions
diff --git a/README b/README
index 7d8191c..04b9440 100644
--- a/README
+++ b/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
 
@@ -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.