[Mongrel-development] [ANN] Unicorn: UNIX+localhost/LAN-only Mongrel fork
ezmobius at gmail.com
Wed Feb 11 19:40:08 EST 2009
This is really cool. I'm going to play with this now and see how it
On Feb 11, 2009, at 3:04 PM, Eric Wong wrote:
> Hello all,
> Last week, I finally decided to put into motion some ideas I've been
> kicking around for a year in my head since last year...
> Basically I don't want to have to deal with threads or support
> that rely on or encourage threads. Especially given MRI 1.9 where
> kernel threads are more difficult to debug than green ones.
> Given the limited scope of this project, I'm thinking it's better to
> a part of the Mongrel project since there is shared code and use
> the Mongrel Rubyforge account for distributing tarballs/gems.
> I don't have the resources or drive to manage things like support,
> documentation, bug-trackers myself. Being a UNIX terminal fart, I
> find the web-based things painful to use. The source is under the
> license as Mongrel and in git (see below) so feel free to
> contribute :)
> Of course I've yet to actually thoroughly test, deploy real
> or even run benchmarks on Unicorn. That'll probably happen later
> or tomorrow...
> Here's the README (also at http://unicorn.bogomips.org/)
> git repository locations are in there, as well.
> ------------------------------- 8< ----------------------------
> = Unicorn: UNIX + LAN/localhost-only fork of Mongrel
> 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.
> == 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
> * 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
> can be loaded within the master). A copy-on-write friendly garbage
> collector like Ruby Enterprise Edition can be used to minimize
> * 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
> Unicorn is copyright 2009 Eric Wong and contributors.
> It is based on Mongrel:
> Mongrel is copyright 2007 Zed A. Shaw and contributors. It is licensed
> under the Ruby license and the GPL2. See the include LICENSE file for
> == Install
> The library consists of a C extension so you'll need a C compiler or
> 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:
> == 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
> Email Eric Wong at normalperson at yhbt.net for now.
> ------------------------------- 8< ----------------------------
> Mongrel-development mailing list
> Mongrel-development at rubyforge.org
ez at engineyard.com
More information about the Mongrel-development