From 32a5a5e91bd78795f546e2a8b8b775f1e1989ed9 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 9 Mar 2009 15:29:59 -0700 Subject: Documentation updates Reformat README to avoid preformatted text. Document signal handling in SIGNALS. Split out DESIGN, it's probably not as useful to end-users Update CONTRIBUTORS LICENSE: copyright is for me (Eric Wong), not Zed since this is a Mongrel fork. --- .document | 2 + CONTRIBUTORS | 5 ++- DESIGN | 80 ++++++++++++++++++++++++++++++++++++ LICENSE | 10 ++--- README | 130 ++++++++++++----------------------------------------------- SIGNALS | 34 ++++++++++++++++ 6 files changed, 149 insertions(+), 112 deletions(-) create mode 100644 DESIGN create mode 100644 SIGNALS diff --git a/.document b/.document index d045955..bff7a40 100644 --- a/.document +++ b/.document @@ -1,7 +1,9 @@ README +DESIGN CHANGELOG CONTRIBUTORS LICENSE +SIGNALS TODO bin lib diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 3268298..ac47dfb 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1,4 +1,7 @@ +Unicorn would not be possible without Zed and all the contributors to Mongrel. +Eric Wong +Ezra Zygmuntowicz Zed A. Shaw Luis Lavena Wilson Bilkovich @@ -10,7 +13,7 @@ Rick Olson Wayne E. Seguin Kirk Haines Bradley Taylor -Matt Pelletier +Matt Pelletier Ry Dahl Nick Sieger Evan Weaver diff --git a/DESIGN b/DESIGN new file mode 100644 index 0000000..cc359ca --- /dev/null +++ b/DESIGN @@ -0,0 +1,80 @@ +== 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 are 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/before_exec hooks be defined inline. An + optional, separate 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 along with the "preload_app true" directive. + +* 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. + +* If the master process dies unexpectedly for any reason, + workers will notice within :timeout/2 seconds and follow + the master to its death. diff --git a/LICENSE b/LICENSE index e5a926e..c02e2c5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ -Mongrel Web Server (Mongrel) is copyrighted free software by Zed A. Shaw - and contributors. You can redistribute it +Unicorn Web Server (unicorn) is copyrighted free software by Eric Wong +(normalperson@yhbt.net) and contributors. You can redistribute it and/or modify it under either the terms of the GPL2 or the conditions below: 1. You may make and give away verbatim copies of the source form of the @@ -41,9 +41,9 @@ and/or modify it under either the terms of the GPL2 or the conditions below: software (possibly commercial). But some files in the distribution are not written by the author, so that they are not under this terms. -5. The scripts and library files supplied as input to or produced as +5. The scripts and library files supplied as input to or produced as output from the software do not automatically fall under the - copyright of the software, but belong to whomever generated them, + copyright of the software, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this software. @@ -51,5 +51,3 @@ and/or modify it under either the terms of the GPL2 or the conditions below: IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - - diff --git a/README b/README index 3c92c15..73bb6d7 100644 --- a/README +++ b/README @@ -6,111 +6,31 @@ proxy we know of that meets this requirement. == Features - * 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/before_exec hooks be defined inline. An - optional, separate 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 along with the "preload_app true" directive. - - * 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. - - * If the master process dies unexpectedly for any reason, - workers will notice within :timeout/2 seconds and follow - the master to its death. +* process management: Unicorn will reap and restart workers that + die because of broken apps and there is no need to manage + multiple processes yourself. + +* does not care 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. + +* supports all Rack applications + +* 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. + +* builtin log rotation via USR1 signal + +* Ruby 1.9-compatible (at least the test cases all pass :>) == License diff --git a/SIGNALS b/SIGNALS new file mode 100644 index 0000000..40f9c3d --- /dev/null +++ b/SIGNALS @@ -0,0 +1,34 @@ +== Signal handling + +In general, signals need only be sent to the master process. However, +the signals unicorn uses internally to communicate with the worker +processes are documented here as well. + +=== Master Process + + * HUP - reload config file and gracefully restart all workers + + * INT/TERM - quick shutdown, kills all workers immediately + + * QUIT - graceful shutdown, waits for workers to finish their + current request before finishing. + + * USR1 - reopen all logs owned by the master and all workers + See Unicorn::Util.reopen_logs for what is considered a log. + + * USR2 - reexecute the running binary. A separate QUIT + should be sent to the original process once the child is verified to + be up and running. + +=== Worker Processes + +Sending signals directly to the worker processes should not normally be +needed. If the master process is running, any exited worker will be +automatically respawned. + + * INT/TERM - quick shutdown, immediately exit + + * QUIT - gracefully exit after finishing the current request + + * USR1 - reopen all logs owned by the worker process + See Unicorn::Util.reopen_logs for what is considered a log. -- cgit v1.2.3-24-ge0c7