tests: remove utee and use tee(1) instead
[rainbows.git] / vs_Unicorn
blob67e42507976e80a8cda1814472f03f4df095a9ea
1 = \Rainbows! is like Unicorn, but Different...
3 While \Rainbows! depends on Unicorn for its process/socket management,
4 HTTP parser and configuration language; \Rainbows! is more ambitious.
6 == Architectural Diagrams
8 === Unicorn uses a 1:1 mapping of processes to clients
10      unicorn master
11      \_ unicorn worker[0]
12      |  \_ client[0]
13      \_ unicorn worker[1]
14      |  \_ client[1]
15      \_ unicorn worker[2]
16      |  \_ client[2]
17      ...
18      \_ unicorn worker[M]
19         \_ client[M]
21 === \Rainbows! uses a M:N mapping of processes to clients
23     rainbows master
24      \_ rainbows worker[0]
25      |  \_ client[0,0]
26      |  \_ client[0,1]
27      |  \_ client[0,2]
28      |  ...
29      |  \_ client[0,N]
30      \_ rainbows worker[1]
31      |  \_ client[1,0]
32      |  \_ client[1,1]
33      |  \_ client[1,2]
34      |  \_ client[1,3]
35      |  ...
36      |  \_ client[1,N]
37      \_ rainbows worker[2]
38      |  \_ client[2,0]
39      |  \_ client[2,1]
40      |  \_ client[2,2]
41      |  ...
42      |  \_ client[2,N]
43      ...
44      \_ rainbows worker[M]
45         \_ client[M,0]
46         \_ client[M,1]
47         \_ client[M,2]
48         ...
49         \_ client[M,N]
51 In both cases, workers share common listen sockets with the master and
52 pull connections off the listen queue only if the worker has resources
53 available.
55 == Differences from Unicorn
57 * log rotation is handled immediately in \Rainbows! whereas Unicorn has
58   the luxury of delaying it until the current request is finished
59   processing to prevent log entries for one request to be split across
60   files.
62 * load balancing between workers is imperfect, certain worker processes
63   may be servicing more requests than others so it is important to not
64   set +worker_connections+ too high.  Unicorn worker processes can never
65   be servicing more than one request at once.
67 * speculative, non-blocking accept() is not used, this is to help
68   load balance between multiple worker processes.
70 * HTTP pipelining and keepalive may be used for GET and HEAD requests.
72 * Less heavily-tested and inherently more complex.
75 == Similarities with Unicorn
77 While some similarities are obvious (we depend on and subclass off
78 Unicorn code), some things are not:
80 * Does not attempt to accept() connections when pre-configured limits
81   are hit (+worker_connections+).  This will first help balance load
82   to different worker processes, and if your listen() +:backlog+ is
83   overflowing: to other machines in your cluster.
85 * Accepts the same {signals}[http://unicorn.bogomips.org/SIGNALS.html]
86   for process management, so you can share scripts to manage them (and
87   nginx, too).
89 * supports per-process listeners, allowing an external load balancer
90   like haproxy or nginx to be used to balance between multiple
91   worker processes.
93 * Exposes a streaming "rack.input" to the Rack application that reads
94   data off the socket as the application reads it (while retaining
95   rewindable semantics as required by Rack).  This allows Rack-compliant
96   apps/middleware to implement things such as real-time upload progress
97   monitoring.