Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Revamp architectural overview

  • Loading branch information...
commit b2318bbb766e8c9293bd2d294a799be2454d6812 1 parent 2c75a53
@FooBarWidget FooBarWidget authored
View
222 doc/Architectural overview.txt
@@ -1,21 +1,22 @@
-Passenger architectural overview
-================================
+Phusion Passenger design & architecture
+=======================================
-This document describes Passenger's architure in a global way. The purpose of
-this document is to lower the barrier to entry for new contributors, as well
-as to explain (some of the) design choices that we have made.
+image:images/phusion_banner.png[link="http://www.phusion.nl/"]
-Or it can be a fun read for people who just want to know how Passenger works.
+This document describes Phusion Passenger's design and architure in a global way. The purpose of
+this document is to lower the barrier to entry for new contributors, as well
+as to explain (some of the) design choices that we have made. Or it can be a fun read
+for people who just want to know how Phusion Passenger works.
-About the involved technologies
--------------------------------
+Introduction to related technologies
+------------------------------------
-[[typical_web_applications]]
-=== Typical web applications ===
+[[web_app_models]]
+=== Web application models ===
-Before we describe Passenger, it is important to understand how typical web
-applications work, from the point of view of someone who wants to connect the
+Before we describe Phusion Passenger, it is important to understand how typical web
+applications work from the viewpoint of someone who wants to connect the
application to a web server.
A typical, isolated, web application accepts an HTTP request from some I/O
@@ -28,32 +29,46 @@ representation of an HTTP request.
image:images/typical_isolated_web_application.png[Architecture of a typical
web application in isolation]
-Few web applications are accessible directly by HTTP clients. Common setups
+Few web applications are accessible directly by HTTP clients. Common models
are:
1. The web application is contained in an application server. This application
server may or may not be able to contain multiple web applications. The
-application server is then connected to the web server. The web server
+application server is then connected to the web server through some kind of
+protocol. This protocol may be HTTP, FastCGI, SCGI, AJP or whatever. The web server
dispatches requests to the application server, which in turn dispatches
requests to the correct web application, in a format that the web application
understands. Conversely, HTTP responses outputted by the web application are
sent to the application server, which in turn sends them to the web server,
and eventually to the HTTP client.
+
-A typical example of such a setup is a J2EE application, contained in the
-Tomcat web server, behind the Apache web server.
+Typical examples of such a model:
++
+ * A J2EE application, contained in the Tomcat application server, proxied
+ behind the Apache web server. Tomcat can contain multiple web applications
+ in a single Tomcat instance.
+ * Most Ruby application servers besides Phusion Passenger (Thin, Unicorn,
+ Goliath, etc). These application servers can only contain a single Ruby
+ web application per instance. They load the web application into their
+ own process and are put behind a web server (Apache, Nginx) in a reverse
+ proxy setup.
2. The web application is contained in a web server. In this case, the web
-server acts like an application server. This is the case for PHP applications,
+server acts like an application server. This is the case for PHP applications
on Apache servers with 'mod_php'. Note that this does not necessarily mean
that the web application is run inside the same process as the web server:
-it just means that the web server manages applications.
+it just means that the web server manages applications. In case of mod_php
+however PHP does run directly inside the Apache worker processes.
++
+Phusion Passenger for Apache and Phusion Passenger for Nginx implement this model.
3. The web application *is* a web server, and can accept HTTP requests
directly. This is the case for the Trac bug tracking system, running in its
-standalone server. In many setups, such web applications sit behind a different
-web server, instead of accepting HTTP requests directly. The frontend web
-server acts like a reverse HTTP proxy.
+standalone server. In most setups they are reverse proxied behind a real
+web server such as Apache or Nginx, instead of accepting HTTP requests directly.
++
+Phusion Passenger Standalone implements this model. You can expose Phusion Passenger
+Standalone directly to the Internet because it uses Nginx internally.
4. The web application does not speak HTTP directly, but is connected directly
to the web server through some communication adapter. CGI, FastCGI and SCGI
@@ -61,13 +76,13 @@ are good examples of this.
These descriptions are true for virtually all web applications, whether they're
based on PHP, Django, J2EE, ASP.NET, Ruby on Rails, or whatever. Note that all
-of these setups provide the same functionality, i.e. no setup can do something
-that a different setup can't. The critical reader will notice that all of these
-setups are identical to the one described in the first diagram, if the
+of these models provide the same functionality, i.e. no model can do something
+that a different model can't. The critical reader will notice that all of these
+models are identical to the one described in the first diagram, if the
combination of web servers, application servers, web applications etc. are
considered to be a single entity; a black box if you will.
-It should also be noted that these setups do not enforce any particular
+It should also be noted that these models do not enforce any particular
I/O processing implementation. The web servers, application servers, web
applications, etc. could process I/O serially (i.e. one request at a time),
could multiplex I/O with a single thread (e.g. by using `select(2)` or
@@ -77,24 +92,68 @@ processes.
Of course, there are many variations possible. For example, load balancers
could be used. But that is outside the scope of this document.
-
-=== Ruby on Rails ===
-
-Every Ruby on Rails application has a 'dispatcher'. This dispatcher is
-responsible for processing HTTP requests. It does not speak HTTP directly.
-Instead, it accepts data structures that contain the information of an
-HTTP request. Thus, the dispatcher is particularly interesting to
-developers who wish to develop software which connects Ruby on Rails to an
-HTTP processing layer (e.g. a web server).
-
-The Ruby on Rails dispatcher can only process requests serially, i.e. one
-at a time. It is not possible to process two requests at the same time
-with threads, because parts of Ruby on Rails are not thread-safe. (In
-practice, this isn't as big of a problem as some people imagine. This will
-be elaborated further in <<concurrent_requests,Handling of concurrent
-requests>>.)
-
-A particularly interesting thing to note, is that a lot of the memory
+==== Why reverse proxy? ====
+
+As you've seen, it is often necessary to put the web application or its
+application server behind a real web server in a reverse proxy setup even
+when the web app/app server already speaks HTTP. This is because implementing
+HTTP in a proper, secure way involves more than just speaking the protocol.
+The public Internet is a hostile environment where clients can send any
+arbitrary data and can exhibit any arbitrary I/O patterns. Web servers like
+Apache and Nginx have already implemented world-class I/O and connection
+handling code and it would be a waste to reinvent their wheel. In the end,
+putting the application in a reverse proxying setup makes the whole system
+more robust and and more secure.
+
+A typical problem involves dealing with *slow clients*. These clients may send
+HTTP requests slowly and read HTTP responses slowly, perhaps taking many seconds
+to complete their work. A naive single-threaded HTTP server implementation
+that reads an HTTP requests, processes, and sends the HTTP response in a loop
+may end up spending so much time waiting for I/O that spends very little time
+doing actual work. Worse: suppose that the client is malicious, just leaves the
+socket open and never reads the HTTP response, then the server will spend
+forever waiting for the client, not being able to handle any more requests.
+
+.An example of a naive HTTP server implementation
+-------------------
+while true
+ client = accept_next_client()
+ request = read_http_request(client)
+ response = process_request(request)
+ send_http_response(client, response)
+end
+-------------------
+
+There are many ways to solve this problem. One could use one thread per client,
+one could implement I/O timeouts, one could use an evented I/O architecture, one
+could have a dedicated I/O thread or process buffer requests and responses.
+The point is, implementing all this properly is non-trivial. Instead of
+reimplementing these over and over in each application server, it's better to
+let a real web server deal with all the details and let the application server
+and the web application do what they're best at: their own core business logic.
+
+
+=== Ruby Rack and Ruby on Rails ===
+
+The de-facto standard interface for Ruby web applications is link:http://rack.rubyforge.org/[Rack].
+Rack specifies an programming interface for web application developers to implement.
+This interface covers HTTP request and response handling, and is not dependent on
+any particular application server. The idea is that any Rack-compliant application
+server can implement the Rack specification and work with all Rack-compliant web applications.
+
+image:images/rack.png[]
+
+In the distant past, each Ruby web framework had its own interface, so application
+servers needed to explicitly add support for each web framework. Nowadays application
+servers just support Rack.
+
+image:images/many_web_framework_protocols.png[]
+
+Ruby on Rails has been fully Rack compliant since version 3.0. Rails 2.3 was partially
+Rack-compliant while earlier versions were not Rack-compliant at all. Phusion Passenger
+supports Rack as well as all Rails 1.x and 2.x versions.
+
+A particularly interesting thing to note is that a lot of the memory
occupied by Ruby on Rails applications is spent on storing the program code
(i.e. the link:http://en.wikipedia.org/wiki/Abstract_syntax_tree[abstract
syntax tree (AST)]) in memory. This is observed through the use of the
@@ -105,54 +164,69 @@ application is spent on bootstrapping the Rails framework.
=== Apache ===
-The Apache web server has a pluggable I/O multiprocessing (the ability to
+The Apache web server has a dynamic module system and a pluggable I/O
+multiprocessing (the ability to
handle more than 1 concurrent HTTP client at the same time) architecture. An
Apache module which implements a particular multiprocessing strategy, is called
-a Multi-Processing Module (MPM). The
-link:http://httpd.apache.org/docs/2.0/mod/prefork.html[prefork MPM] -- which
-also happens to be the default -- appears to be the most popular one. This MPM
-spawns multiple worker child processes. HTTP requests are first accepted by a
+a Multi-Processing Module (MPM). The single-threaded multi-process
+link:http://httpd.apache.org/docs/2.4/mod/prefork.html[prefork MPM] had been
+the default and the most popular one for a long time, but in recent times the
+hybrid multi-threaded/multi-process link:http://httpd.apache.org/docs/2.4/mod/worker.html[worker MPM]
+is becoming increasingly popular because of its better performance and scalability.
+Furthermore, Apache 2.4 introduced the link:http://httpd.apache.org/docs/2.4/mod/event.html[event MPM]
+which is a hybrid evented/multi-threaded/multi-process MPM and offers even more
+scalability benefits.
+
+The prefork MPM remains in wide use today because it's the only MPM that works well with mod_php.
+
+The prefork MPM spawns multiple worker child processes. HTTP requests are first accepted by a
so-called control process, and then forwarded to one of the worker processes.
The next section contains a diagram which shows the prefork MPM's architecture.
-Passenger architecture
-----------------------
+=== Nginx ===
+
+Nginx is a lightweight web server that is becoming increasingly popular. It is known
+to be smaller, lighter weight and more scalable than Apache thanks to its evented I/O
+architecture. That said, Nginx is less flexible than Apache. For example it has no
+dynamic module system: all modules must be statically compiled into Nginx.
+
+
+Phusion Passenger architecture
+------------------------------
=== Overview ===
-Passenger's architecture is a lot like setup #2 described in
-<<typical_web_applications,Typical web applications>>. In other words,
-Passenger extends Apache and allows it to act like an application server.
-Passenger's architecture -- assuming Apache 2 with the prefork MPM is used --
-is shown in the following diagram:
+Phusion Passenger's architecture is a lot like model #2 described in
+<<web_app_models,Web application models>>. In other words,
+Phusion Passenger extends Apache/Nginx and allows it to act like an
+application server. This is shown in the following diagram:
image:images/passenger_architecture.png[Passenger's architecture]
-Passenger consists of an Apache module, 'mod_passenger'. This is written in
-C++, and can be found in the directory 'ext/apache2'. The module is active in
-the Apache control process and in all the Apache worker processes. When an
-HTTP request comes in, 'mod_passenger' will check whether the request should
-be handled by a Ruby on Rails application. If so, then 'mod_passenger' will
-spawn the corresponding Rails application (if necessary) and forward the
-request to that application.
+Phusion Passenger consists of:
+
+* an Apache module, 'mod_passenger'. This is written in C++, and can be found in the directory 'ext/apache2'.
+* an Nginx module 'ngx_http_passenger_module'. This is written in C, and can be found in the directory 'ext/nginx'.
+* Common code used by both the Apache and the Nginx module. For example the helper agent is among this code. This code is mostly C++ and can be found in the directory 'ext/common'.
+
+The module is active all Apache/Nginx processes. When an HTTP request comes in, the Phusion Passenger module checks whether the request should be handled by a Phusion Passenger-served application. If so, then the module spawns one or more processes for the corresponding application (if necessary), forwards the request to that application process and forwards its generated response back to the client. This is all done with the assistance of the Phusion Passenger helper agent, which stores state that must be shared among all web server worker processes and handles much of the internal I/O between the web server and the application processes.
-It should be noted that the Ruby on Rails application does *not* run in the
-same address space as Apache. This differentiates Passenger from other
+It should be noted that applications do *not* run in the same address space as the web server.
+This differentiates Passenger from other
application-server-inside-web-server software such as mod_php, mod_perl and
-mod_ruby. If the Rails application crashes or leak memory, it will have no
-effect on Apache. In fact, stability is one of our highest goals. Passenger
-is carefully designed and implemented so that Apache shouldn't crash because
-of Passenger.
+mod_ruby. If the application crashes or leak memory, it will have no
+effect on the web server. In fact, stability is one of our highest goals. Phusion Passenger
+is carefully designed and implemented so that the web server shouldn't crash because
+of Phusion Passenger.
=== Spawning and caching of code and applications ===
-A very naive implementation of Passenger would spawn a Ruby on Rails
-application every time an HTTP request is received, just like CGI would.
-However, spawning Ruby on Rails applications is expensive. It can take 1 or 2
-seconds on a modern PC, and possibly much longer on a heavily loaded server.
-This overhead is particularily unacceptable on shared hosts. A less naive
-implementation would keep spawned Ruby on Rails application instances alive,
+A very naive implementation of an application server would spawn an application
+process every time an HTTP request is received, just like CGI would.
+However, spawning Ruby applications is typically expensive. It can take a few
+seconds on a modern computer, and possibly much longer on a heavily loaded server.
+A less naive implementation would keep spawned application processes alive,
similar to how Lighttpd's FastCGI implementation works.
However, this still has several problems:
View
BIN  doc/images/many_web_framework_protocols.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  doc/images/passenger_architecture.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
413 doc/images/passenger_architecture.svg
@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
+ xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="690"
- height="255"
+ width="673"
+ height="300"
id="svg2"
sodipodi:version="0.32"
- inkscape:version="0.45.1"
- sodipodi:docbase="/home/hongli/Projects/mod_rails/doc/images"
+ inkscape:version="0.48.2 r9819"
sodipodi:docname="passenger_architecture.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.0"
- inkscape:export-filename="/home/hongli/Projects/mod_rails/doc/images/passenger_architecture.png"
+ inkscape:export-filename="/Users/hongli/Projects/passenger/doc/images/passenger_architecture.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
@@ -28,7 +28,8 @@
width="1.0953077"
y="-0.14720792"
height="1.2944158"
- id="filter3347">
+ id="filter3347"
+ color-interpolation-filters="sRGB">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="6.195"
@@ -40,7 +41,8 @@
width="1.1655581"
y="-0.26366666"
height="1.5273333"
- id="filter3525">
+ id="filter3525"
+ color-interpolation-filters="sRGB">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="6.6568168"
@@ -52,7 +54,8 @@
width="1.1920769"
y="-0.24508251"
height="1.490165"
- id="filter3674">
+ id="filter3674"
+ color-interpolation-filters="sRGB">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="5.7001074"
@@ -70,16 +73,18 @@
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="1"
- inkscape:cx="368.19518"
- inkscape:cy="12.720779"
+ inkscape:cx="356.69124"
+ inkscape:cy="197.81434"
inkscape:document-units="px"
inkscape:current-layer="layer1"
- inkscape:window-width="1280"
- inkscape:window-height="702"
- inkscape:window-x="0"
- inkscape:window-y="72"
+ inkscape:window-width="1345"
+ inkscape:window-height="860"
+ inkscape:window-x="-1"
+ inkscape:window-y="0"
height="255px"
- width="690px" />
+ width="690px"
+ showgrid="false"
+ inkscape:window-maximized="0" />
<metadata
id="metadata7">
<rdf:RDF>
@@ -88,6 +93,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
@@ -95,109 +101,89 @@
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
- transform="translate(80.588234,-91.862183)">
+ transform="translate(80.588234,-46.862183)">
<path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 343,161.36218 L 446,161.36218"
- id="path3521" />
+ style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 185,160.86218 0,62"
+ id="path3252"
+ inkscape:connector-curvature="0" />
<path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 186,208.86218 L 186,270.86218"
- id="path3252" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 365.38655,271.36218 L 365.38655,238.86218 L 14,238.86218 L 14,270.36218"
- id="path3265" />
+ style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 364.38655,223.36218 0,-32.5 -351.38655,0 0,31.5"
+ id="path3265"
+ inkscape:connector-curvature="0" />
<g
id="g3351"
- transform="translate(-73,14)">
+ transform="translate(-74,-34)">
<rect
- transform="matrix(1.0224359,0,0,1.0224359,-8.445513,-3.2404977)"
+ transform="matrix(0.74039317,0,0,1.0224359,66.297144,-3.2404977)"
ry="25"
- rx="25"
+ rx="34.523411"
y="99.862183"
x="109"
height="101"
width="312"
id="rect3282"
- style="opacity:0.78500001;fill:#000000;fill-opacity:1;stroke:none;stroke-width:3.99999952;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter3347)" />
+ style="opacity:0.78500001;fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter3347)" />
<g
transform="translate(0.5,1.5)"
id="g3267">
<rect
- style="fill:#98caff;fill-opacity:1;stroke:#4f90c9;stroke-width:3.99999952;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ style="fill:#98caff;fill-opacity:1;stroke:#4f90c9;stroke-width:3.99999952;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect2160"
- width="312"
+ width="225"
height="101"
- x="102"
+ x="146"
y="92.362183"
- rx="25"
+ rx="25.000002"
ry="25" />
<text
xml:space="preserve"
- style="font-size:25.89120865px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- x="194.89148"
- y="129.91624"
+ style="font-size:25.89120865px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ x="257.86023"
+ y="116.91624"
id="text2162"><tspan
sodipodi:role="line"
id="tspan2164"
- x="194.89148"
- y="129.91624"
- style="font-weight:bold">Apache</tspan></text>
+ x="257.86023"
+ y="116.91624"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Helvetica Bold">Apache/Nginx</tspan><tspan
+ sodipodi:role="line"
+ x="257.86023"
+ y="136.91623"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Helvetica Bold"
+ id="tspan3806">master process</tspan></text>
<g
id="g3162"
- transform="translate(131,-14)">
+ transform="translate(175,-14)">
<rect
ry="10"
- rx="10.546875"
+ rx="10"
y="163.36218"
x="-11"
height="30"
- width="135"
+ width="193"
id="rect3160"
- style="opacity:1;fill:#bbf6ff;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ style="fill:#bbf6ff;fill-opacity:1;stroke:none" />
<text
id="text2166"
- y="181.62328"
- x="1.8492519"
- style="font-size:13.65985012px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ y="182.62328"
+ x="3.8492508"
+ style="font-size:13.65985012px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
- y="181.62328"
- x="1.8492519"
+ y="182.62328"
+ x="3.8492508"
id="tspan2168"
- sodipodi:role="line">mod_passenger</tspan></text>
- </g>
- <g
- id="g3178"
- transform="translate(55,-1.5)">
- <rect
- ry="10"
- rx="10.546875"
- y="150.36218"
- x="209.5"
- height="30"
- width="135"
- id="rect3169"
- style="fill:#bbf6ff;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <text
- id="text3171"
- y="168.62328"
- x="222.34926"
- style="font-size:13.65985012px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- xml:space="preserve"><tspan
- y="168.62328"
- x="222.34926"
- id="tspan3173"
- sodipodi:role="line">Application pool</tspan></text>
+ sodipodi:role="line">Phusion Passenger code</tspan></text>
</g>
</g>
</g>
<g
id="g3529"
- transform="translate(50,14)">
+ transform="translate(33,-38)">
<rect
transform="matrix(0.9504893,0,0,0.9504893,23.279218,5.1572528)"
- style="opacity:0.76999996;fill:#000000;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter3525)"
+ style="opacity:0.76999996;fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter3525)"
id="rect3523"
width="193"
height="60.593021"
@@ -209,7 +195,7 @@
transform="translate(41,31)"
id="g3516">
<rect
- style="opacity:1;fill:#baf94d;fill-opacity:1;stroke:#8adf27;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ style="fill:#baf94d;fill-opacity:1;stroke:#8adf27;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3514"
width="172"
height="54"
@@ -219,183 +205,180 @@
ry="20" />
<text
xml:space="preserve"
- style="font-size:19.99363899px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- x="335.47308"
- y="121.29496"
+ style="font-size:19.99363899px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ x="337.47308"
+ y="122.29496"
id="text2170"><tspan
sodipodi:role="line"
id="tspan2172"
- x="335.47308"
- y="121.29496">Spawn server</tspan></text>
+ x="337.47308"
+ y="122.29496">Helper agent</tspan></text>
</g>
</g>
<g
id="g3678"
- transform="translate(-0.363961,-0.4142136)">
+ transform="translate(-1.363961,-48.414214)">
<rect
- transform="matrix(1.0223382,0,0,1.0223382,46.463881,-22.382629)"
- ry="15"
- rx="15"
+ transform="matrix(1.0341163,0,0,1.5994034,47.821744,-181.69881)"
+ ry="9.5879955"
+ rx="14.829157"
y="289.76028"
x="-101.60646"
height="55.818989"
width="142.44562"
id="rect3608"
- style="opacity:0.72000002;fill:#000000;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter3674)" />
+ style="opacity:0.72000002;fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter3674)" />
<rect
ry="15"
- rx="15"
+ rx="14.999999"
y="270.62689"
- x="-58.088234"
- height="55.818989"
+ x="-58.08823"
+ height="93.818993"
width="142.44562"
id="rect2182"
- style="fill:#ffe99b;fill-opacity:1;stroke:#ffb63e;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ style="fill:#ffe99b;fill-opacity:1;stroke:#ffb63e;stroke-width:2.99999976;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<text
id="text2178"
y="293.17538"
- x="-45.983486"
- style="font-size:15.85331345px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="13.431603"
+ style="font-size:15.85331345px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="293.17538"
- x="-45.983486"
+ x="13.431602"
id="tspan2180"
- sodipodi:role="line">Worker process</tspan></text>
- <g
- transform="translate(6.363961,4.596194)"
- id="g3603">
- <rect
- style="fill:#fffeda;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect3554"
- width="85.5"
- height="19"
- x="-39.088226"
- y="295.86218"
- rx="6.6796875"
- ry="6.3333335" />
- <text
- xml:space="preserve"
- style="font-size:8.65123844px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- x="-28.829058"
- y="308.48822"
- id="text3556"><tspan
- sodipodi:role="line"
- id="tspan3558"
- x="-28.829058"
- y="308.48822">mod_passenger</tspan></text>
- </g>
- </g>
- <g
- id="g3688"
- transform="translate(172.67465,-0.5545786)">
+ sodipodi:role="line">Web server</tspan><tspan
+ y="312.99203"
+ x="13.431602"
+ sodipodi:role="line"
+ id="tspan3808">worker process</tspan></text>
<rect
- transform="matrix(1.0223382,0,0,1.0223382,46.463881,-22.382629)"
- ry="15"
- rx="15"
- y="289.76028"
- x="-101.60646"
- height="55.818989"
- width="142.44562"
- id="rect3690"
- style="opacity:0.72000002;fill:#000000;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter3674)" />
+ ry="6.3333335"
+ rx="6.679687"
+ y="327.45837"
+ x="-47.724266"
+ height="25"
+ width="121.5"
+ id="rect3554"
+ style="fill:#fffeda;fill-opacity:1;stroke:none" />
+ <text
+ id="text3556"
+ y="343.08441"
+ x="-39.465096"
+ style="font-size:8.65123844px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="343.08441"
+ x="-39.465096"
+ id="tspan3558"
+ sodipodi:role="line">Phusion Passenger code</tspan></text>
<rect
- ry="15"
- rx="15"
- y="270.62689"
- x="-58.088234"
+ style="opacity:0.72000002;fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter3674)"
+ id="rect3829"
+ width="142.44562"
height="55.818989"
+ x="-101.60646"
+ y="289.76028"
+ rx="14.829157"
+ ry="9.5879955"
+ transform="matrix(1.0341163,0,0,1.5994034,218.82174,-180.69881)" />
+ <rect
+ style="fill:#ffe99b;fill-opacity:1;stroke:#ffb63e;stroke-width:2.99999976;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3831"
width="142.44562"
- id="rect3692"
- style="fill:#ffe99b;fill-opacity:1;stroke:#ffb63e;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ height="93.818993"
+ x="112.91177"
+ y="271.62689"
+ rx="14.999999"
+ ry="15" />
<text
- id="text3694"
- y="293.17538"
- x="-45.983486"
- style="font-size:15.85331345px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- xml:space="preserve"><tspan
- y="293.17538"
- x="-45.983486"
- id="tspan3696"
- sodipodi:role="line">Worker process</tspan></text>
- <g
- transform="translate(6.363961,4.596194)"
- id="g3698">
- <rect
- style="fill:#fffeda;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect3700"
- width="85.5"
- height="19"
- x="-39.088226"
- y="295.86218"
- rx="6.6796875"
- ry="6.3333335" />
- <text
- xml:space="preserve"
- style="font-size:8.65123844px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- x="-28.829058"
- y="308.48822"
- id="text3702"><tspan
- sodipodi:role="line"
- id="tspan3704"
- x="-28.829058"
- y="308.48822">mod_passenger</tspan></text>
- </g>
- </g>
- <g
- id="g3706"
- transform="translate(352.09823,-0.6593946)">
+ xml:space="preserve"
+ style="font-size:15.85331345px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ x="184.43161"
+ y="294.17538"
+ id="text3833"><tspan
+ sodipodi:role="line"
+ id="tspan3835"
+ x="184.43161"
+ y="294.17538">Web server</tspan><tspan
+ id="tspan3837"
+ sodipodi:role="line"
+ x="184.43161"
+ y="313.99203">worker process</tspan></text>
<rect
- transform="matrix(1.0223382,0,0,1.0223382,46.463881,-22.382629)"
- ry="15"
- rx="15"
+ style="fill:#fffeda;fill-opacity:1;stroke:none"
+ id="rect3839"
+ width="121.5"
+ height="25"
+ x="123.27573"
+ y="328.45837"
+ rx="6.679687"
+ ry="6.3333335" />
+ <text
+ xml:space="preserve"
+ style="font-size:8.65123844px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ x="131.53491"
+ y="344.08441"
+ id="text3841"><tspan
+ sodipodi:role="line"
+ id="tspan3843"
+ x="131.53491"
+ y="344.08441">Phusion Passenger code</tspan></text>
+ <rect
+ transform="matrix(1.0341163,0,0,1.5994034,399.82174,-179.69881)"
+ ry="9.5879955"
+ rx="14.829157"
y="289.76028"
x="-101.60646"
height="55.818989"
width="142.44562"
- id="rect3708"
- style="opacity:0.72000002;fill:#000000;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter3674)" />
+ id="rect3845"
+ style="opacity:0.72000002;fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter3674)" />
<rect
ry="15"
- rx="15"
- y="270.62689"
- x="-58.088234"
- height="55.818989"
+ rx="14.999999"
+ y="272.62689"
+ x="293.91177"
+ height="93.818993"
width="142.44562"
- id="rect3710"
- style="fill:#ffe99b;fill-opacity:1;stroke:#ffb63e;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ id="rect3847"
+ style="fill:#ffe99b;fill-opacity:1;stroke:#ffb63e;stroke-width:2.99999976;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<text
- id="text3712"
- y="293.17538"
- x="-45.983486"
- style="font-size:15.85331345px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ id="text3849"
+ y="295.17538"
+ x="365.43161"
+ style="font-size:15.85331345px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
- y="293.17538"
- x="-45.983486"
- id="tspan3714"
- sodipodi:role="line">Worker process</tspan></text>
- <g
- transform="translate(6.363961,4.596194)"
- id="g3716">
- <rect
- style="fill:#fffeda;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect3718"
- width="85.5"
- height="19"
- x="-39.088226"
- y="295.86218"
- rx="6.6796875"
- ry="6.3333335" />
- <text
- xml:space="preserve"
- style="font-size:8.65123844px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- x="-28.829058"
- y="308.48822"
- id="text3720"><tspan
- sodipodi:role="line"
- id="tspan3722"
- x="-28.829058"
- y="308.48822">mod_passenger</tspan></text>
- </g>
+ y="295.17538"
+ x="365.43161"
+ id="tspan3851"
+ sodipodi:role="line">Web server</tspan><tspan
+ y="314.99203"
+ x="365.43161"
+ sodipodi:role="line"
+ id="tspan3853">worker process</tspan></text>
+ <rect
+ ry="6.3333335"
+ rx="6.679687"
+ y="329.45837"
+ x="304.27573"
+ height="25"
+ width="121.5"
+ id="rect3855"
+ style="fill:#fffeda;fill-opacity:1;stroke:none" />
+ <text
+ id="text3857"
+ y="345.08441"
+ x="312.53491"
+ style="font-size:8.65123844px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="345.08441"
+ x="312.53491"
+ id="tspan3859"
+ sodipodi:role="line">Phusion Passenger code</tspan></text>
</g>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 364.41177,190.86218 110,0 0,-54"
+ id="path3861"
+ inkscape:connector-curvature="0" />
</g>
</svg>
View
BIN  doc/images/rack.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Please sign in to comment.
Something went wrong with that request. Please try again.