JezK
Edit File: page-DESIGN.ri
U:RDoc::TopLevel[ i I"DESIGN:ETcRDoc::Parser::Simpleo:RDoc::Markup::Document:@parts[S:RDoc::Markup::Heading: leveli: textI"Design;To:RDoc::Markup::BlankLine o:RDoc::Markup::List: @type:BULLET:@items[o:RDoc::Markup::ListItem:@label0;[o:RDoc::Markup::Paragraph;[I"CSimplicity: Unicorn is a traditional UNIX prefork web server. ;TI"INo threads are used at all, this makes applications easier to debug ;TI"@and fix. When your application goes awry, a BOFH can just ;TI"I"kill -9" the runaway worker process without worrying about tearing ;TI"Dall clients down, just one. Only UNIX-like systems supporting ;TI":fork() and file descriptor inheritance are supported.;T@ o;;0;[o;;[I"3The Ragel+C HTTP parser is taken from Mongrel.;T@ o;;0;[o;;[I"8All HTTP parsing and I/O is done much like Mongrel:;To:RDoc::Markup::Verbatim;[I"01. read/parse HTTP request headers in full ;TI"2. call Rack application ;TI"/3. write HTTP response back to the client ;T:@format0o;;0;[o;;[ I"CLike Mongrel, neither keepalive nor pipelining are supported. ;TI"AThese aren't needed since Unicorn is only designed to serve ;TI"Dfast, low-latency clients directly. Do one thing, do it well; ;TI"#let nginx handle slow clients.;T@ o;;0;[o;;[I"?Configuration is purely in Ruby and eval(). Ruby is less ;TI".ambiguous than YAML and lets lambdas for ;TI"Ebefore_fork/after_fork/before_exec hooks be defined inline. An ;TI"Doptional, separate config_file may be used to modify supported ;TI"Jconfiguration changes (and also gives you plenty of rope if you RTFS ;TI":>);T@ o;;0;[o;;[I"@One master process spawns and reaps worker processes. The ;TI"KRack application itself is called only within the worker process (but ;TI"Ican be loaded within the master). A copy-on-write friendly garbage ;TI"Ccollector like the one found in mainline Ruby 2.0.0 and later ;TI"Lcan be used to minimize memory usage along with the "preload_app true" ;TI"+directive (see Unicorn::Configurator).;T@ o;;0;[o;;[I"FThe number of worker processes should be scaled to the number of ;TI"FCPUs, memory or even spindles you have. If you have an existing ;TI"HMongrel cluster on a single-threaded app, using the same amount of ;TI"Gprocesses should work. Let a full-HTTP-request-buffering reverse ;TI"Jproxy like nginx manage concurrency to thousands of slow clients for ;TI"Iyou. Unicorn scaling should only be concerned about limits of your ;TI"backend system(s).;T@ o;;0;[o;;[ I"GLoad balancing between worker processes is done by the OS kernel. ;TI"AAll workers share a common set of listener sockets and does ;TI"Inon-blocking accept() on them. The kernel will decide which worker ;TI"Dprocess to give a socket to and workers will sleep if there is ;TI"nothing to accept().;T@ o;;0;[o;;[ I"DSince non-blocking accept() is used, there can be a thundering ;TI">herd when an occasional client connects when application ;TI"C*is not busy*. The thundering herd problem should not affect ;TI"Gapplications that are running all the time since worker processes ;TI"Ewill only select()/accept() outside of the application dispatch.;T@ o;;0;[o;;[I"?Additionally, thundering herds are much smaller than with ;TI"Kconfigurations using existing prefork servers. Process counts should ;TI"Lonly be scaled to backend resources, _never_ to the number of expected ;TI"Lclients like is typical with blocking prefork servers. So while we've ;TI"Fseen instances of popular prefork servers configured to run many ;TI"Jhundreds of worker processes, Unicorn deployments are typically only ;TI"2-4 processes per-core.;T@ o;;0;[o;;[I"HOn-demand scaling of worker processes never happens automatically. ;TI"LAgain, Unicorn is concerned about scaling to backend limits and should ;TI"Enever configured in a fashion where it could be waiting on slow ;TI"Jclients. For extremely rare circumstances, we provide TTIN and TTOU ;TI"Hsignal handlers to increment/decrement your process counts without ;TI"Hreloading. Think of it as driving a car with manual transmission: ;TI"?you have a lot more control if you know what you're doing.;T@ o;;0;[o;;[ I"HBlocking I/O is used for clients. This allows a simpler code path ;TI"Dto be followed within the Ruby interpreter and fewer syscalls. ;TI"?Applications that use threads continue to work if Unicorn ;TI".is only serving LAN or localhost clients.;T@ o;;0;[o;;[I"NSIGKILL is used to terminate the timed-out workers from misbehaving apps ;TI"Ias reliably as possible on a UNIX system. The default timeout is a ;TI"6generous 60 seconds (same default as in Mongrel).;T@ o;;0;[o;;[ I"BThe poor performance of select() on large FD sets is avoided ;TI"6as few file descriptors are used in each worker. ;TI"@There should be no gain from moving to highly scalable but ;TI">unportable event notification solutions for watching few ;TI"file descriptors.;T@ o;;0;[o;;[I"=If the master process dies unexpectedly for any reason, ;TI">workers will notice within :timeout/2 seconds and follow ;TI"the master to its death.;T@ o;;0;[o;;[ I"GThere is never any explicit real-time dependency or communication ;TI"=between the worker processes nor to the master process. ;TI"ESynchronization is handled entirely by the OS kernel and shared ;TI"Eresources are never accessed by the worker when it is servicing ;TI"a client.;T: @file@:0@omit_headings_from_table_of_contents_below0