From 3be825a50f0d9f7aa443e277a1b6c6bb667c1fb1 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 11 Feb 2009 14:21:20 -0800 Subject: Update documentation --- README | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 127 insertions(+), 7 deletions(-) (limited to 'README') 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. -- cgit v1.2.3-24-ge0c7