passenger 5.0.14 → 5.0.15

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (70) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/CHANGELOG +9 -0
  5. data/INSTALL.md +1 -1
  6. data/LICENSE +1 -1
  7. data/README.md +1 -1
  8. data/bin/passenger-install-apache2-module +6 -10
  9. data/bin/passenger-install-nginx-module +6 -9
  10. data/doc/CloudLicensingConfiguration.html +1 -216
  11. data/doc/CloudLicensingConfiguration.txt.md +1 -192
  12. data/doc/Design and Architecture.html +4 -4
  13. data/doc/Design and Architecture.txt +4 -4
  14. data/doc/ServerOptimizationGuide.html +1 -489
  15. data/doc/ServerOptimizationGuide.txt.md +1 -399
  16. data/doc/Users guide Apache.html +594 -6720
  17. data/doc/Users guide Apache.idmap.txt +15 -12
  18. data/doc/Users guide Apache.txt +113 -2047
  19. data/doc/Users guide Nginx.html +565 -6720
  20. data/doc/Users guide Nginx.idmap.txt +15 -12
  21. data/doc/Users guide Nginx.txt +94 -1862
  22. data/doc/Users guide Standalone.html +53 -2183
  23. data/doc/Users guide Standalone.idmap.txt +9 -6
  24. data/doc/Users guide Standalone.txt +16 -360
  25. data/doc/Users guide.html +3 -145
  26. data/doc/Users guide.txt +2 -54
  27. data/doc/users_guide_snippets/analysis_and_system_maintenance.txt +36 -175
  28. data/doc/users_guide_snippets/appendix_c_spawning_methods.txt +9 -215
  29. data/doc/users_guide_snippets/environment_variables.txt +11 -243
  30. data/doc/users_guide_snippets/installation.txt +66 -946
  31. data/doc/users_guide_snippets/rackup_specifications.txt +1 -75
  32. data/doc/users_guide_snippets/support_information.txt +1 -48
  33. data/doc/users_guide_snippets/tips.txt +103 -704
  34. data/doc/users_guide_snippets/troubleshooting/default.txt +16 -130
  35. data/doc/users_guide_snippets/troubleshooting/rails.txt +15 -12
  36. data/doc/users_guide_snippets/under_the_hood/relationship_with_ruby.txt +2 -113
  37. data/ext/apache2/Configuration.hpp +2 -2
  38. data/ext/apache2/Hooks.cpp +2 -2
  39. data/ext/common/AgentsStarter.h +18 -10
  40. data/ext/common/ApplicationPool2/ErrorRenderer.h +0 -3
  41. data/ext/common/ApplicationPool2/Options.h +8 -1
  42. data/ext/common/Constants.h +3 -9
  43. data/ext/common/agent/Core/RequestHandler/InitRequest.cpp +2 -0
  44. data/ext/common/agent/Watchdog/Main.cpp +1 -1
  45. data/ext/nginx/ContentHandler.c +2 -3
  46. data/ext/nginx/config +2 -2
  47. data/lib/phusion_passenger.rb +1 -22
  48. data/lib/phusion_passenger/abstract_installer.rb +10 -10
  49. data/lib/phusion_passenger/config/agent_compiler.rb +5 -5
  50. data/lib/phusion_passenger/config/nginx_engine_compiler.rb +4 -4
  51. data/lib/phusion_passenger/config/validate_install_command.rb +3 -3
  52. data/lib/phusion_passenger/constants.rb +1 -5
  53. data/lib/phusion_passenger/loader_shared_helpers.rb +16 -5
  54. data/lib/phusion_passenger/platform_info/apache_detector.rb +2 -2
  55. data/lib/phusion_passenger/public_api.rb +11 -2
  56. data/lib/phusion_passenger/request_handler/thread_handler.rb +2 -3
  57. data/lib/phusion_passenger/ruby_core_io_enhancements.rb +4 -1
  58. data/lib/phusion_passenger/standalone/start_command.rb +1 -1
  59. data/resources/oss-binaries.phusionpassenger.com.crt +124 -0
  60. data/resources/templates/apache2/deployment_example.txt.erb +5 -23
  61. data/resources/templates/apache2/installing_against_a_different_apache.txt.erb +3 -4
  62. data/resources/templates/apache2/possible_solutions_for_compilation_and_installation_problems.txt.erb +3 -3
  63. data/resources/templates/apache2/rpm_installation_recommended.txt.erb +1 -1
  64. data/resources/templates/installer_common/low_amount_of_memory_warning.txt.erb +4 -5
  65. data/resources/templates/nginx/deployment_example.txt.erb +5 -17
  66. data/resources/templates/nginx/possible_solutions_for_compilation_and_installation_problems.txt.erb +3 -3
  67. data/resources/templates/standalone/config.erb +1 -1
  68. data/resources/templates/undisclosed_error.html.template +4 -11
  69. metadata +2 -2
  70. metadata.gz.asc +7 -7
@@ -1513,7 +1513,7 @@ Queuing requests and limiting concurrency. Each process tells the ApplicationPoo
1513
1513
  <span class="anchor_helper" id="spawner_subsystem"></span><h3 data-anchor="spawner_subsystem">3.3. The Spawner subsystem</h3>
1514
1514
  <div class="paragraph"><p>The Spawner subsystem is a sub-subsystem within ApplicationPool. It is responsible for actually spawning application processes, and then creating Process objects with the correct information in it.</p></div>
1515
1515
  <div class="paragraph"><p>The <span class="monospaced">Spawner</span> interface encapsulates all low-level process spawning logic. Pool calls Spawner whenever it needs to spawn another application process.</p></div>
1516
- <div class="paragraph"><p>Recall that Phusion Passenger supports multiple spawn methods. For example, the <span class="monospaced">smart</span> spawn method spawns processes through an intermediate preloader process, and can utilize copy-on-write. This is explained in detail in <a href="Users%20guide%20Nginx.html#spawning_methods_explained">Spawn methods explained</a> in the Phusion Passenger manual. Each spawn method corresponds to a different implementation of the Spawner interface. The following implementations are available:</p></div>
1516
+ <div class="paragraph"><p>Recall that Phusion Passenger supports multiple spawn methods. For example, the <span class="monospaced">smart</span> spawn method spawns processes through an intermediate preloader process, and can utilize copy-on-write. This is explained in detail in <a href="https://www.phusionpassenger.com/library/indepth/spawn_methods/">Spawn methods explained</a> in the Phusion Passenger manual. Each spawn method corresponds to a different implementation of the Spawner interface. The following implementations are available:</p></div>
1517
1517
  <div class="ulist"><ul>
1518
1518
  <li>
1519
1519
  <p>
@@ -1548,7 +1548,7 @@ DummySpawner (not shown in diagram) — only used in unit tests.
1548
1548
  </span></p></div>
1549
1549
  <div class="sect3">
1550
1550
  <span class="anchor_helper" id="basic_setup_and_forking"></span><h4 data-anchor="basic_setup_and_forking">4.1.1. Basic setup and forking</h4>
1551
- <div class="paragraph"><p>Spawning begins when the <span class="monospaced">spawn()</span> method is called on a <a href="#spawner_subsystem">Spawner object</a>. The Spawner determines <a href="Users%20guide%20Nginx.html#user_switching">which user the process should run as</a>, and sets up some communication channels (anonymous Unix domain socket pairs), and forks a process. The parent waits until the child exits, or replies with something over the communication channel.</p></div>
1551
+ <div class="paragraph"><p>Spawning begins when the <span class="monospaced">spawn()</span> method is called on a <a href="#spawner_subsystem">Spawner object</a>. The Spawner determines <a href="https://www.phusionpassenger.com/library/deploy/nginx/user_sandboxing.html">which user the process should run as</a>, and sets up some communication channels (anonymous Unix domain socket pairs), and forks a process. The parent waits until the child exits, or replies with something over the communication channel.</p></div>
1552
1552
  <div class="paragraph"><p>The communication channel in question is — from the viewpoint of the (pre)loader — actually just stdin, stdout and stderr! The anonymous Unix domain socket pairs that the Spawner creates, is mapped to the child process’s stdin, stdout and stderr file descriptors. Thus, Spawner sends data to the (pre)loader by writing stuff to its stdin, and the (pre)loader sends data back to the Spawner by writing stuff to stdout or stderr.</p></div>
1553
1553
  </div>
1554
1554
  <div class="sect3">
@@ -1569,7 +1569,7 @@ DummySpawner (not shown in diagram) — only used in unit tests.
1569
1569
  If the target user’s shell is bash, and the <span class="monospaced">passenger_load_shell_envvars</span> option is turned on:
1570
1570
  </p>
1571
1571
  <div class="paragraph"><p><span class="monospaced">bash -l -c '/path-to/SpawnPreparer /path-to-loader-or-preloader'</span></p></div>
1572
- <div class="paragraph"><p>This causes bash to load its startup files, e.g. bashrc, profile, etc, after which it executes the SpawnPreparer with the given parameters. The reason why we do this is because a lot of users try to set environment variables in their bashrc, and they expect these environment variables to be picked up by applications spawned by Phusion Passenger. Unfortunately environment variables <a href="Users%20guide%20Nginx.html#about_environment_variables">don’t work that way</a>, but we support it anyway because it is good for usability.</p></div>
1572
+ <div class="paragraph"><p>This causes bash to load its startup files, e.g. bashrc, profile, etc, after which it executes the SpawnPreparer with the given parameters. The reason why we do this is because a lot of users try to set environment variables in their bashrc, and they expect these environment variables to be picked up by applications spawned by Phusion Passenger. Unfortunately environment variables <a href="https://www.phusionpassenger.com/library/indepth/environment_variables.html">don’t work that way</a>, but we support it anyway because it is good for usability.</p></div>
1573
1573
  </li>
1574
1574
  <li>
1575
1575
  <p>
@@ -1808,7 +1808,7 @@ No more clients will be routed to this particular process.
1808
1808
  </div>
1809
1809
  <div class="sect2">
1810
1810
  <span class="anchor_helper" id="preloaders"></span><h3 data-anchor="preloaders">4.3. Preloaders</h3>
1811
- <div class="paragraph"><p>Preloaders are a special kind of loaders, used for reducing spawn time and leveraging copy-on-write. You can learn more about this at <a href="Users%20guide%20Nginx.html#spawning_methods_explained">Spawning methods explained</a>.</p></div>
1811
+ <div class="paragraph"><p>Preloaders are a special kind of loaders, used for reducing spawn time and leveraging copy-on-write. You can learn more about this at <a href="https://www.phusionpassenger.com/library/indepth/spawn_methods/">Spawning methods explained</a>.</p></div>
1812
1812
  <div class="paragraph"><p>Preloaders look a lot like loaders, but behave slightly differently. They also use stdin, stderr and stdout to communicate with the Spawner. The protocols are very similar.</p></div>
1813
1813
  <div class="paragraph"><p>A preloader initializes in 4 stages:</p></div>
1814
1814
  <div class="olist arabic"><ol class="arabic">
@@ -243,7 +243,7 @@ The Spawner subsystem is a sub-subsystem within ApplicationPool. It is responsib
243
243
 
244
244
  The `Spawner` interface encapsulates all low-level process spawning logic. Pool calls Spawner whenever it needs to spawn another application process.
245
245
 
246
- Recall that Phusion Passenger supports multiple spawn methods. For example, the `smart` spawn method spawns processes through an intermediate preloader process, and can utilize copy-on-write. This is explained in detail in link:Users%20guide%20Nginx.html#spawning_methods_explained[Spawn methods explained] in the Phusion Passenger manual. Each spawn method corresponds to a different implementation of the Spawner interface. The following implementations are available:
246
+ Recall that Phusion Passenger supports multiple spawn methods. For example, the `smart` spawn method spawns processes through an intermediate preloader process, and can utilize copy-on-write. This is explained in detail in link:https://www.phusionpassenger.com/library/indepth/spawn_methods/[Spawn methods explained] in the Phusion Passenger manual. Each spawn method corresponds to a different implementation of the Spawner interface. The following implementations are available:
247
247
 
248
248
  * DirectSpawner -- implements the `direct` spawn method.
249
249
  * SmartSpawner -- implements the `smart` spawn method.
@@ -268,7 +268,7 @@ image:images/spawning_preparation_work.png[Spawning preparation work]
268
268
  [[basic_setup_and_forking]]
269
269
  ==== Basic setup and forking
270
270
 
271
- Spawning begins when the `spawn()` method is called on a <<spawner_subsystem,Spawner object>>. The Spawner determines link:Users%20guide%20Nginx.html#user_switching[which user the process should run as], and sets up some communication channels (anonymous Unix domain socket pairs), and forks a process. The parent waits until the child exits, or replies with something over the communication channel.
271
+ Spawning begins when the `spawn()` method is called on a <<spawner_subsystem,Spawner object>>. The Spawner determines link:https://www.phusionpassenger.com/library/deploy/nginx/user_sandboxing.html[which user the process should run as], and sets up some communication channels (anonymous Unix domain socket pairs), and forks a process. The parent waits until the child exits, or replies with something over the communication channel.
272
272
 
273
273
  The communication channel in question is -- from the viewpoint of the (pre)loader -- actually just stdin, stdout and stderr! The anonymous Unix domain socket pairs that the Spawner creates, is mapped to the child process's stdin, stdout and stderr file descriptors. Thus, Spawner sends data to the (pre)loader by writing stuff to its stdin, and the (pre)loader sends data back to the Spawner by writing stuff to stdout or stderr.
274
274
 
@@ -287,7 +287,7 @@ To execute the SpawnPreparer, the child process executes one of the following co
287
287
  +
288
288
  `bash -l -c '/path-to/SpawnPreparer /path-to-loader-or-preloader'`
289
289
  +
290
- This causes bash to load its startup files, e.g. bashrc, profile, etc, after which it executes the SpawnPreparer with the given parameters. The reason why we do this is because a lot of users try to set environment variables in their bashrc, and they expect these environment variables to be picked up by applications spawned by Phusion Passenger. Unfortunately environment variables link:Users%20guide%20Nginx.html#about_environment_variables[don't work that way], but we support it anyway because it is good for usability.
290
+ This causes bash to load its startup files, e.g. bashrc, profile, etc, after which it executes the SpawnPreparer with the given parameters. The reason why we do this is because a lot of users try to set environment variables in their bashrc, and they expect these environment variables to be picked up by applications spawned by Phusion Passenger. Unfortunately environment variables link:https://www.phusionpassenger.com/library/indepth/environment_variables.html[don't work that way], but we support it anyway because it is good for usability.
291
291
 
292
292
  * Otherwise, the SpawnPreparer is executed directly, without bash:
293
293
  +
@@ -441,7 +441,7 @@ While the Spawner is still doing its work, it takes care of this forwarding by i
441
441
  [[preloaders]]
442
442
  === Preloaders
443
443
 
444
- Preloaders are a special kind of loaders, used for reducing spawn time and leveraging copy-on-write. You can learn more about this at link:Users%20guide%20Nginx.html#spawning_methods_explained[Spawning methods explained].
444
+ Preloaders are a special kind of loaders, used for reducing spawn time and leveraging copy-on-write. You can learn more about this at link:https://www.phusionpassenger.com/library/indepth/spawn_methods/[Spawning methods explained].
445
445
 
446
446
  Preloaders look a lot like loaders, but behave slightly differently. They also use stdin, stderr and stdout to communicate with the Spawner. The protocols are very similar.
447
447
 
@@ -136,495 +136,7 @@
136
136
 
137
137
  <h1>Server optimization guide</h1>
138
138
 
139
- <p>There are two aspects with regard to optimizing Phusion Passenger performance.</p>
140
-
141
- <p>The first aspect is <em>settings tuning</em>. Phusion Passenger's default settings are not aimed at optimizing, but at <em>safety</em>. The defaults are designed to conserve resources, to prevent server overload and to keep web apps up and running. To optimize for performance, you need to tweak some settings whose values depend on your hardware and your environment.</p>
142
-
143
- <p>Besides Phusion Passenger settings, you may also want to tune kernel-level settings.</p>
144
-
145
- <p>The second aspect is <em>using performance-enhancing features</em>. This requires small application-level changes.</p>
146
-
147
- <p>If you are optimizing Phusion Passenger for the purpose of <strong>benchmarking</strong> then you should also follow the benchmarking recommendations.</p>
148
-
149
- <p><a name="minimizing_process_spawning"></a></p>
150
-
151
- <h2>Minimizing process spawning</h2>
152
-
153
- <p>By default, Phusion Passenger spawns and shuts down application processes according to traffic. This allows it to use more resources during busy times, while conserving resources during idle times. This is especially useful if you host more than 1 app on a single server: if not all apps are used at the same time, then you don't have to keep all apps running at the same time.</p>
154
-
155
- <p>However, spawning a process takes a lot of time (in the order of 10-20 seconds for a Rails app), and CPU usage will be near 100% during spawning. Therefore, while spawning, your server will be slower at performing other activities, such as handling requests.</p>
156
-
157
- <p>For consistent performance, it is thus recommended that you configure a static process pool: telling Phusion Passenger to use a fixed number of processes, instead of spawning and shutting them down dynamically.</p>
158
-
159
- <h3>Standalone</h3>
160
-
161
- <p>Run <code>passenger start</code> with <code>--max-pool-size=N --min-instances=N</code>, where <code>N</code> is the number of processes you want.</p>
162
-
163
- <h3>Nginx</h3>
164
-
165
- <p>Let <code>N</code> be the number of processes you want. Set the following configuration in your <code>http</code> block:</p>
166
-
167
- <pre><code>passenger_max_pool_size N;
168
- </code></pre>
169
-
170
- <p>Set the following configuration in your <code>server</code> block:</p>
171
-
172
- <pre><code>passenger_min_instances N;
173
- </code></pre>
174
-
175
- <p>You should also configure <code>passenger_pre_start</code> in the <code>http</code> block so that your app is started during web server launch:</p>
176
-
177
- <pre><code># Refer to the Users Guide for more information about passenger_pre_start.
178
- passenger_pre_start http://your-website-url.com;
179
- </code></pre>
180
-
181
- <h3>Apache</h3>
182
-
183
- <p>Let <code>N</code> be the number of processes you want. Set the following configuration in the global context:</p>
184
-
185
- <pre><code>PassengerMaxPoolSize N
186
- </code></pre>
187
-
188
- <p>Set the following configuration in your virtual host block:</p>
189
-
190
- <pre><code>PassengerMinInstances N
191
- </code></pre>
192
-
193
- <p>You should also configure <code>PassengerPreStart</code> in the global context so that your app is started during web server launch:</p>
194
-
195
- <pre><code># Refer to the Users Guide for more information about PassengerPreStart.
196
- PassengerPreStart http://your-website-url.com
197
- </code></pre>
198
-
199
- <h2>Maximizing throughput</h2>
200
-
201
- <p>This section provides guidance on maximizing Phusion Passenger's throughput. The amount of throughput that Phusion Passenger handles is proportional to the number of processes or threads that you've configured. More processes/threads generally means more throughput, but there is an upper limit. Past a certain value, further increasing the number of processes/threads won't help. If you increase the number of processes/threads even further, then performance may even go down.</p>
202
-
203
- <p>The optimal value depends on the hardware and the environment. This section will provide you with formulas to calculate that optimal value. The following factors are involved in calculation:</p>
204
-
205
- <ul>
206
- <li><strong>Memory</strong>. More processes implies a higher memory usage. If too much memory is used then the machine will hit swap, which slows everything down. You should only have as many processes as memory limits comfortably allow. Threads use less memory, so prefer threads when possible. You can create tens of threads in place of one process.</li>
207
- <li><p><strong>Number of CPUs</strong>. True (hardware) concurrency cannot be higher than the number of CPUs. In theory, if all processes/threads on your system use the CPUs constantly, then:</p>
208
-
209
- <ul>
210
- <li>You can increase throughput up to <code>NUMBER_OF_CPUS</code> processes/threads.</li>
211
- <li>Increasing the number of processes/threads after that point will increase virtual (software) concurrency, but will not increase true (hardware) concurrency and will not increase maximum throughput.</li>
212
- </ul>
213
-
214
-
215
- <p>Having more processes than CPUs may decrease total throughput a little thanks to context switching overhead, but the difference is not big because OSes are good at context switching these days.</p>
216
-
217
- <p>On the other hand, if your CPUs are not used constantly, e.g. because they’re often blocked on I/O, then the above does not apply and increasing the number of processes/threads does increase concurrency and throughput, at least until the CPUs are saturated.</p></li>
218
- <li><p><strong>Blocking I/O</strong>. This covers all blocking I/O, including hard disk access latencies, database call latencies, web API calls, etc. Handling input from the client and output to the client does not count as blocking I/O, because Phusion Passenger has buffering layers that relief the application from worrying about this.</p>
219
-
220
- <p>The more blocking I/O calls your application process/thread makes, the more time it spends on waiting for external components. While it’s waiting it does not use the CPU, so that’s when another process/thread should get the chance to use the CPU. If no other process/thread needs CPU right now (e.g. all processes/threads are waiting for I/O) then CPU time is essentially wasted. Increasing the number processes or threads decreases the chance of CPU time being wasted. It also increases concurrency, so that clients do not have to wait for a previous I/O call to be completed before being served.</p></li>
221
- </ul>
222
-
223
-
224
- <p>The formulas in this section assume that your machine is dedicated to Phusion Passenger. If your machine also hosts other software (e.g. a database) then you'll need to tweak the formulas a little bit.</p>
225
-
226
- <h3>Tuning the application process and thread count</h3>
227
-
228
- <h4>Step 1: determining the application's memory usage</h4>
229
-
230
- <p>The amount of memory that your application uses on a per-process basis, is key to our calculation. You should first figure out how much memory your application typically needs. Every application has different memory usage patterns, so the typical memory usage is best determined by observation.</p>
231
-
232
- <p>Run your app for a while, then run <code>passenger-status</code> at different points in time to examine memory usage. Then calculate the average of your data points. In the rest of this section, we'll refer to the amount of memory (in MB) that an application process needs, as <code>RAM_PER_PROCESS</code>.</p>
233
-
234
- <p>In our experience, a typical medium-sized single-threaded Rails application process can use 150 MB of RAM on a 64-bit machine, even when the spawning method is set to "smart".</p>
235
-
236
- <h4>Step 2: determine the system's limits</h4>
237
-
238
- <p>First, let's define the maximum number of (single-threaded) processes, or the total number of threads, that you can comfortably have given the amount of RAM you have. This is a reasonable upper limit that you can reach without degrading system performance. This number is not the final optimal number, but is merely used for further caculations in later steps.</p>
239
-
240
- <p>There are two formulas that we can use, depending on what kind of concurrency model your application is using in production.</p>
241
-
242
- <p><strong>Purely single-threaded multi-process formula</strong></p>
243
-
244
- <p>If you didn't explicitly configure multithreading, then you are using using this concurrency model. Or, if you are <em>not</em> using Ruby (e.g. if you using <strong>Python, Node.js or Meteor</strong>), then you are also using this concurrency model, because Phusion Passenger only supports multithreading for Ruby apps.</p>
245
-
246
- <p>The formula is then as follows:</p>
247
-
248
- <pre><code>max_app_processes = (TOTAL_RAM * 0.75) / RAM_PER_PROCESS
249
- </code></pre>
250
-
251
- <p>It is derived as follows:</p>
252
-
253
- <ul>
254
- <li><code>(TOTAL_RAM * 0.75)</code>: We can assume that there must be at least 25% of free RAM that the operating system can use for other things. The result of this calculation is the RAM that is freely available for applications. If your system runs a lot of services and thus has less memory available for Phusion Passenger and its apps, then you should lower <code>0.75</code> to some constant that you think is appropriate.</li>
255
- <li><code>/ RAM_PER_PROCESS</code>: Each process consumes a roughly constant amount of RAM, so the maximum number of processes is a single devision between the aforementioned calculation and this constant.</li>
256
- </ul>
257
-
258
-
259
- <p><strong>Multithreaded formula</strong></p>
260
-
261
- <p>The formula for multithreaded concurrency is as follows:</p>
262
-
263
- <pre><code>max_app_threads_per_process =
264
- ((TOTAL_RAM * 0.75) - (CHOSEN_NUMBER_OF_PROCESSES * RAM_PER_PROCESS * 0.9)) /
265
- (RAM_PER_PROCESS / 10) /
266
- CHOSEN_NUMBER_OF_PROCESSES
267
- </code></pre>
268
-
269
- <p>Here, <code>CHOSEN_NUMBER_OF_PROCESSES</code> is the number of application processes you want to use. In case of Ruby, Python, Node.js and Meteor, this should be equal to <code>NUMBER_OF_CPUS</code>. This is because all these languages can only utilize a single CPU core per process. If you're using a language runtime that does not have a Global Interpreter Lock, e.g. JRuby or Rubinius, then <code>CHOSEN_NUMBER_OF_PROCESSES</code> can be 1.</p>
270
-
271
- <p>The formula is derived as follows:</p>
272
-
273
- <ul>
274
- <li><code>(TOTAL_RAM * 0.75)</code>: The same as explained earlier.</li>
275
- <li><code>(CHOSEN_NUMBER_OF_PROCESSES * RAM_PER_PROCESS * 0.9)</code>: This calculates the amount of memory that all the processes together would consume, assuming they're not running any threads. When this is deducted from <code>TOTAL_RAM * 0.75</code>, we end up with the amount of RAM available to application threads.</li>
276
- <li><code>/ (RAM_PER_PROCESS / 10)</code>: We estimate that a thread consumes ~10% of the amount of memory a process would, so we divide the amount of RAM available to threads with this number. What we get is the number of threads that the system can handle.</li>
277
- </ul>
278
-
279
-
280
- <p>On 32-bit systems, <code>max_app_threads_per_process</code> should not be higher than about 200. Assuming an 8 MB stack size per thread, you will run out of virtual address space if you go much further. On 64-bit systems you don’t have to worry about this problem.</p>
281
-
282
- <h4>Step 3: derive the applications' needs</h4>
283
-
284
- <p>The earlier two formulas were not for calculating the number of processes or threads that application needs, but for calculating how much the system can handle without getting into trouble. Your application may not actually need that many processes or threads! If your application is CPU-bound, then you only need a small multiple of the number of CPUs you have. Only if your application performs a lot of blocking I/O (e.g. database calls that take tens of milliseconds to complete, or you call to Twitter) do you need a large number of processes or threads.</p>
285
-
286
- <p>Armed with this knowledge, we derive the formulas for calculating how many processes or threads we actually need.</p>
287
-
288
- <ul>
289
- <li><p>If your application performs a lot of blocking I/O then you should give it as many processes and threads as possible:</p>
290
-
291
- <pre><code># Use this formula for purely single-threaded multi-process scenarios.
292
- desired_app_processes = max_app_processes
293
-
294
- # Use this formula for multithreaded scenarios.
295
- desired_app_threads_per_process = max_app_threads_per_process
296
- </code></pre></li>
297
- <li><p>If your application doesn’t perform a lot of blocking I/O, then you should limit the number of processes or threads to a multiple of the number of CPUs to minimize context switching:</p>
298
-
299
- <pre><code># Use this formula for purely single-threaded multi-process scenarios.
300
- desired_app_processes = min(max_app_processes, NUMBER_OF_CPUS)
301
-
302
- # Use this formula for multithreaded scenarios.
303
- desired_app_threads_per_process = min(max_app_threads_per_process, 2 * NUMBER_OF_CPUS)
304
- </code></pre></li>
305
- </ul>
306
-
307
-
308
- <h4>Step 3: configure Phusion Passenger</h4>
309
-
310
- <p><strong>Purely single-threaded multi-process scenarios</strong></p>
311
-
312
- <ul>
313
- <li>When using Phusion Passenger Standalone, run <code>passenger start</code> with <code>--max-pool-size=&lt;desired_app_processes&gt; --min-instances=&lt;desired_app_processes&gt;</code>.</li>
314
- <li>When using Phusion Passenger for Nginx, configure:
315
-
316
- <ul>
317
- <li><code>passenger_max_pool_size &lt;desired_app_processes&gt;;</code></li>
318
- <li><code>passenger_min_instances &lt;desired_app_processes&gt;;</code></li>
319
- <li><code>passenger_pre_start</code> to have your app started automatically at web server boot.</li>
320
- </ul>
321
- </li>
322
- <li>When using Phusion Passenger for Apache, configure:
323
-
324
- <ul>
325
- <li><code>PassengerMaxPoolSize &lt;desired_app_processes&gt;</code></li>
326
- <li><code>PassengerMinInstances &lt;desired_app_processes&gt;</code></li>
327
- <li><code>PassengerPreStart</code> to have your app started automatically at web server boot.</li>
328
- </ul>
329
- </li>
330
- </ul>
331
-
332
-
333
- <p><strong>Multithreaded scenarios</strong></p>
334
-
335
- <p>In order to use multithreading you must use Phusion Passenger Enterprise. The open source version of Phusion Passenger does not support multithreading.</p>
336
-
337
- <ul>
338
- <li>When using Phusion Passenger Standalone:
339
-
340
- <ul>
341
- <li>Run <code>passenger start</code> with <code>--max-pool-size=&lt;CHOSEN_NUMBER_OF_PROCESSES&gt; --min-instances=&lt;CHOSEN_NUMBER_OF_PROCESSES&gt; --concurrency-model=thread --thread-count=&lt;desired_app_threads_per_process&gt;</code></li>
342
- <li>If <code>desired_app_processes</code> is 1, then you should also add <code>--spawn-method=direct</code>. By using direct spawning instead of smart spawning, Phusion Passenger will not keep a Preloader process around, saving you some memory. This is because a Preloader process is useless when there's only 1 application process.</li>
343
- </ul>
344
- </li>
345
- <li>When using Phusion Passenger for Nginx, configure:
346
-
347
- <ul>
348
- <li><code>passenger_max_pool_size &lt;CHOSEN_NUMBER_OF_PROCESSES&gt;;</code></li>
349
- <li><code>passenger_min_instances &lt;CHOSEN_NUMBER_OF_PROCESSES&gt;;</code></li>
350
- <li><code>passenger_concurrency_model thread;</code></li>
351
- <li><code>passenger_thread_count &lt;desired_app_threads_per_process&gt;;</code></li>
352
- <li><code>passenger_pre_start</code> to have your app started automatically at web server boot.</li>
353
- <li>If <code>desired_app_processes</code> is 1, then you should set <code>passenger_spawn_method direct</code>. By using direct spawning instead of smart spawning, Phusion Passenger will not keep a Preloader process around, saving you some memory. This is because a Preloader process is useless when there's only 1 application process.</li>
354
- </ul>
355
- </li>
356
- <li>When using Phusion Passenger for Apache, configure:
357
-
358
- <ul>
359
- <li><code>PassengerMaxPoolSize &lt;desired_app_processes&gt;</code></li>
360
- <li><code>PassengerMinInstances &lt;desired_app_processes&gt;</code></li>
361
- <li><code>PassengerConcurrencyModel thread</code></li>
362
- <li><code>PassengerThreadCount &lt;desired_app_threads_per_process&gt;</code></li>
363
- <li><code>PassengerPreStart</code> to have your app started automatically at web server boot.</li>
364
- <li>If <code>desired_app_processes</code> is 1, then you should set <code>PassengerSpawnMethod direct</code>. By using direct spawning instead of smart spawning, Phusion Passenger will not keep a Preloader process around, saving you some memory. This is because a Preloader process is useless when there's only 1 application process.</li>
365
- </ul>
366
- </li>
367
- </ul>
368
-
369
-
370
- <h4>Possible step 4: configure Rails</h4>
371
-
372
- <p>Only if you're using the multithreaded concurrency model do you need to configure Rails. You need to enable thread-safety by setting <code>config.thread_safe!</code> in <code>config/environments/production.rb</code>. In Rails 4.0 this is on by default for the production environment, but in earlier versions you had to enable it manually.</p>
373
-
374
- <p>You should also increase the ActiveRecord pool size because it limits concurrency. You can configure it in <code>config/database.yml</code>. Set the <code>pool</code> value to the number of threads per application process. But if you believe your database cannot handle that much concurrency, keep it at a low value.</p>
375
-
376
- <h4>Example 1: purely single-threaded multi-process scenario with lots of blocking I/O, in a low-memory server</h4>
377
-
378
- <p>Suppose you have:</p>
379
-
380
- <ul>
381
- <li>1 GB of RAM.</li>
382
- <li>150 MB of memory usage per application process.</li>
383
- <li>Lots of blocking I/O in the application.</li>
384
- <li>A purely single-threaded multi-process scenario.</li>
385
- </ul>
386
-
387
-
388
- <p>Then the calculation is as follows:</p>
389
-
390
- <pre><code># Use this formula for purely single-threaded multi-process deployments.
391
- max_app_processes = (1024 * 0.75) / 150 = 5.12
392
- desired_app_processes = max_app_processes = 5.12
393
- </code></pre>
394
-
395
- <p>Conclusion: you should use 5 or 6 processes. Phusion Passenger should be configured as follows:</p>
396
-
397
- <pre><code># Standalone
398
- passenger start --max-pool-size=5 --min-instances=5
399
-
400
- # Nginx
401
- passenger_max_pool_size 5;
402
- passenger_min_instances 5;
403
-
404
- # Apache
405
- PassengerMaxPoolSize 5
406
- PassengerMinInstances 5
407
- </code></pre>
408
-
409
- <p>However a concurrency of 5 or 6 is way too low if your application performs a lot of blocking I/O. You should use a multithreaded deployment instead, or you need to get more RAM so you can run more processes.</p>
410
-
411
- <h4>Example 2: purely single-threaded multi-process scenario with lots of blocking I/O, in a high-memory server</h4>
412
-
413
- <p>Suppose you have:</p>
414
-
415
- <ul>
416
- <li>8 CPUs.</li>
417
- <li>32 GB of RAM.</li>
418
- <li>150 MB of memory usage per application process.</li>
419
- <li>Lots of blocking I/O in the application.</li>
420
- <li>A purely single-threaded multi-process scenario.</li>
421
- </ul>
422
-
423
-
424
- <p>Then the calculation is as follows:</p>
425
-
426
- <pre><code># Use this formula for purely single-threaded multi-process deployments.
427
- max_app_processes = (1024 * 32 * 0.75) / 150 = 163.84
428
- desired_app_processes = max_app_processes = 163.84
429
- </code></pre>
430
-
431
- <p>Conclusion: you should use 163 or 164 processes. This number seems high, but the value is correct. Because your app performs a lot of blocking I/O, you need a lot of I/O concurrency. The more concurrency the better. The amount of concurrency scales linearly with the number of processes, which is why you end up with such a large number.</p>
432
-
433
- <p>Phusion Passenger should be configured as follows:</p>
434
-
435
- <pre><code># Standalone
436
- passenger start --max-pool-size=163 --min-instances=163
437
-
438
- # Nginx
439
- passenger_max_pool_size 163;
440
- passenger_min_instances 163;
441
-
442
- # Apache
443
- PassengerMaxPoolSize 163
444
- PassengerMinInstances 163
445
- </code></pre>
446
-
447
- <p>Note that in this example, 163-164 processes is merely the maximum number of processes that you can run, without overloading your RAM. It does not mean that you have enough concurrency for your application! If you need more concurrency, you should use a multithreaded deployment instead.</p>
448
-
449
- <h4>Example 3: multithreaded deployment with lots of blocking I/O</h4>
450
-
451
- <p>Consider the same machine as in example 2:</p>
452
-
453
- <ul>
454
- <li>8 CPUs.</li>
455
- <li>32 GB of RAM.</li>
456
- <li>150 MB of memory usage per application process.</li>
457
- <li>Lots of blocking I/O in the application.</li>
458
- <li>A purely single-threaded multi-process scenario.</li>
459
- </ul>
460
-
461
-
462
- <p>But this time you're using multithreading with 8 application processes (because you have 8 CPUs). How many threads do you need per process?</p>
463
-
464
- <pre><code># Use this formula for multithreaded deployments.
465
- max_app_threads_per_process
466
- = ((1024 * 32 * 0.75) - (8 * 150)) / (150 / 10) / 8
467
- = 194.8
468
- </code></pre>
469
-
470
- <p>Conclusion: you should use 195 threads per process.</p>
471
-
472
- <pre><code># Standalone
473
- passenger start --max-pool-size=8 --min-instances=8 --concurrency-model=thread --thread-count=195
474
-
475
- # Nginx
476
- passenger_max_pool_size 8;
477
- passenger_min_instances 8;
478
- passenger_concurrency_model thread;
479
- passenger_thread_count 195;
480
-
481
- # Apache
482
- PassengerMaxPoolSize 8
483
- PassengerMinInstances 8
484
- PassengerConcurrencyModel thread
485
- PassengerThreadCount 195
486
- </code></pre>
487
-
488
- <p>Because of the huge number of threads, this only works on a 64-bit platform. If you're on a 32-bit platform, consider lowering the number of threads while raising the number of processes. For example, you can double the number of processes (to 16) and halve the number of threads (to 779).</p>
489
-
490
- <h3>Configuring the web server</h3>
491
-
492
- <p>If you're using Nginx then it does not need additional configuration. Nginx is evented and already supports a high concurrency out of the box.</p>
493
-
494
- <p>If you're using Apache, then prefer the worker MPM (which uses a combination of processes and threads) or the event MPM (which is similar to the worker MPM, but better) over the prefork MPM (which only uses processes) whenever possible. PHP requires prefork, but if you don't use PHP then you can probably use one of the other MPMs. Make sure you set a low number of processes and a moderate to high number of threads.</p>
495
-
496
- <p>Because Apache performs a lot of blocking I/O (namely HTTP handling), you should give it a lot of threads so that it has a lot of concurrency. Apache's concurrency <em>must</em> be somewhat larger than the total number of application processes or total number of application threads. When considering example 3, the Apache concurrency must be larger than <code>8 * 1558 = 12464</code>.</p>
497
-
498
- <p>If you cannot use the event MPM, consider putting Apache behind an Nginx reverse proxy, with response buffering turned on on the Nginx side. This reliefs a lot of concurrency problems from Apache. If you can use the event MPM then adding Nginx to the mix does not provide many advantages.</p>
499
-
500
- <h3>Summary</h3>
501
-
502
- <ul>
503
- <li>If your application performs a lot of blocking I/O, use lots of processes/threads. You should move away from single-threaded multiprocessing in this case, and start using multithreading.</li>
504
- <li>If your application is CPU-bound, use a small multiple of the number of CPUs.</li>
505
- <li>Do not exceed the number of processes/threads your system can handle without swapping.</li>
506
- </ul>
507
-
508
-
509
- <h2>Performance-enhancing features</h2>
510
-
511
- <p><a name="turbocaching"></a></p>
512
-
513
- <h3>Turbocaching</h3>
514
-
515
- <p>Phusion Passenger supports turbocaching since version 4. Turbocaching is an HTTP cache built inside Phusion Passenger. When used correctly, the cache can accelerate your app tremendously. To utilize turbocaching, you only need to set HTTP caching headers.</p>
516
-
517
- <h4>Learning about HTTP caching headers</h4>
518
-
519
- <p>The first thing you should do is to <a href="https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching">learn how to use HTTP caching headers</a>. It's pretty simple and straightforward. Since the turbocache is just a normal HTTP shared cache, it respects all the HTTP caching rules.</p>
520
-
521
- <h4>Set an Expires or Cache-Control header</h4>
522
-
523
- <p>To activate the turbocache, the response must contain either an "Expires" header or a "Cache-Control" header.</p>
524
-
525
- <p>The "Expires" header tells the turbocache how long to cache a response. Its value is an HTTP timestamp, e.g. "Thu, 01 Dec 1994 16:00:00 GMT".</p>
526
-
527
- <p>The Cache-Control header is a more advanced header that not only allows you to set the caching time, but also how the cache should behave. The easiest way to use it is to set the <strong>max-age</strong> flag, which has the same effect as setting "Expires". For example, this tells the turbocache that the response is cacheable for at most 60 seconds:</p>
528
-
529
- <pre><code>Cache-Control: max-age=60
530
- </code></pre>
531
-
532
- <p>As you can see, a "Cache-Control" header is much easier to generate than an "Expires" header. Furthermore, "Expires" doesn't work if the visitor's computer's clock is wrongly configured, while "Cache-Control" does. This is why we recommend using "Cache-Control".</p>
533
-
534
- <p>Another flag to be aware of is the <strong>private</strong> flag. This flag tells any shared caches -- caches which are meant to store responses for many users -- not to cache the response. The turbocache is a shared cache. However, the browser's cache is not, so the browser can still cache the response. You should set the "private" flag on responses which are meant for a single user, as you will learn later in this article.</p>
535
-
536
- <p>And finally, there is the <strong>no-store</strong> flag, which tells <em>all</em> caches -- even the browser's -- not to cache the response.</p>
537
-
538
- <p>Here is an example of a response which is cacheable for 60 seconds by the browser's cache, but not by the turbocache:</p>
539
-
540
- <pre><code>Cache-Control: max-age=60,private
541
- </code></pre>
542
-
543
- <p>The HTTP specification specifies a bunch of other flags, but they're not relevant for the turbocache.</p>
544
-
545
- <h4>Only GET requests are cacheable</h4>
546
-
547
- <p>The turbocache currently only caches GET requests. POST, PUT, DELETE and other requests are never cached. If you want your response to be cacheable by the turbocache, be sure to use GET requests, but also be sure that your request is idempotent.</p>
548
-
549
- <h4>Avoid using the "Vary" header</h4>
550
-
551
- <p>The "Vary" header is used to tell caches that the response depends on one or more request headers. But the turbocache does not implement support for the "Vary" header, so if you output a "Vary" header then the turbocache will not cache your response at all. Avoid using the "Vary" header where possible.</p>
552
-
553
- <h4>Maximum response size</h4>
554
-
555
- <p>The turbocache caches only responses that are at most 32 KB, including HTTP headers. This maximum size is currently not configurable, but <a href="https://github.com/phusion/passenger/issues/1430">we are working on it</a>.</p>
556
-
557
- <h4>Maximum caching time</h4>
558
-
559
- <p>The turbocache caches a response for a maximum duration of 2 seconds, or whatever is specified as the expiry time according to the HTTP headers, whichever is earliest. The cap of 2 seconds is currently not configurable, but <a href="https://github.com/phusion/passenger/issues/1430">we are working on it</a>.</p>
560
-
561
- <h3>Out-of-band garbage collection</h3>
562
-
563
- <p>Phusion Passenger supports out-of-band garbage collection for Ruby apps. With this feature enabled, Phusion Passenger can run the garbage collector in between requests, so that the garbage collector doesn't delay the app as much. Please refer to the Users Guide for more information about this feature.</p>
564
-
565
- <h3>Using the builtin HTTP engine</h3>
566
-
567
- <p>In certain situations, using the builtin HTTP engine in Passenger Standalone may yield some performance benefits because it skips a layer of processing.</p>
568
-
569
- <p>Passenger normally works by integrating into Nginx or Apache. As described in the <a href="Design%20and%20Architecture.html">Design &amp; Architecture</a> document, requests are first handled by Nginx or Apache, and then forwarded to the Passenger core process (the Passenger core) and the application process. This architecture provides various benefits, such as security benefits (Nginx and Apache's HTTP connection handling routines are thoroughly battle-tested and secure) and feature benefits (e.g. Gzip compression, superb static file handling).</p>
570
-
571
- <p>This is even true if you use the Standalone mode. Although it acts standalone, it is implemented under the hood by running Passenger in a builtin Nginx engine.</p>
572
-
573
- <p>However, the fact that all requests go through Nginx or Apache means that there is a slight overhead, which can be avoided. This overhead is small (much smaller than typical application and network overhead), and using Nginx or Apache is very useful, but in certain special situations it may be beneficial to skip this layer.</p>
574
-
575
- <ul>
576
- <li>In <strong>microbenchmarks</strong>, the overhead of Nginx and Apache are very noticeable. Removing Nginx and Apache from the setup, and benchmarking against the Passenger core directly, will yield much better results.</li>
577
- <li>In some <strong>multi-server setups</strong>, Nginx and Apache may be redundant. Recall that in typical multi-server setups there is a load balancer which forwards requests to one of the many web servers. Each web server in this setup runs Passenger. But the load balancer is sometimes already responsible for many of the tasks that Nginx and Apache perform, e.g. the secure handling of HTTP connections, buffering, slow client protection or even static file serving. In these cases, removing Nginx and Apache from the web servers and load balancing to the Passenger core directly may have a minor improvement on performance.</li>
578
- </ul>
579
-
580
-
581
- <p>Nginx and Apache can be removed by using Passenger's builtin HTTP engine. By using this engine, Passenger will listen directly on a socket for HTTP requests, without using Nginx or Apache.</p>
582
-
583
- <p>This builtin HTTP engine can be accessed by starting Passenger Standalone using the <code>--engine=builtin</code> parameter, like this:</p>
584
-
585
- <pre><code>passenger start --engine=builtin
586
- </code></pre>
587
-
588
- <p>It should be noted that the builtin HTTP engine has fewer features than the Nginx engine, by design. For example the builtin HTTP engine does not support serving static files, nor does it support gzip compression. Thus, we recommend using the Nginx engine in most situations, unless you have special needs such as documented above.</p>
589
-
590
- <h2>Benchmarking recommendations</h2>
591
-
592
- <h3>Tooling recommendations</h3>
593
-
594
- <ul>
595
- <li>Use <a href="https://github.com/wg/wrk">wrk</a> as benchmarking tool.
596
-
597
- <ul>
598
- <li>We do not recommend <code>ab</code> because it's slow and buggy.</li>
599
- <li>We do not recommend <code>siege</code> and <code>httperf</code> because they cannot utilize multiple CPU cores.</li>
600
- </ul>
601
- </li>
602
- <li>Enable HTTP keep-alive in both the server and in your benchmarking tool. Otherwise you will end up benchmarking how quickly the kernel can set up TCP connections, which is a non-trivial part of the request time.</li>
603
- <li>Warm up the server before benchmarking. That is, run a mini-benchmark before the actual benchmark, and discard the result of the mini-benchmark.</li>
604
- </ul>
605
-
606
-
607
- <h3>Operating system recommendations</h3>
608
-
609
- <ul>
610
- <li>Don't benchmark on OS X. OS X's TCP stack and process scheduler are horrible from a performance point of view. We recommend Linux.</li>
611
- <li>When on Linux, be sure to <a href="http://www.joedog.org/articles-tuning/">tune your kernel socket settings</a> so that they don't stall the benchmark.</li>
612
- </ul>
613
-
614
-
615
- <h3>Server and application recommendations</h3>
616
-
617
- <ul>
618
- <li>If the purpose of your benchmark is to compare against Puma, Unicorn or other app servers, be sure to benchmark against Phusion Passenger Standalone, not Phusion Passenger for Nginx or Phusion Passenger for Apache.
619
-
620
- <ul>
621
- <li>This is because Puma, Unicorn and other app servers are standalone servers, while Phusion Passenger for Nginx and Phusion Passenger for Apache introduce additional layers (namely Nginx and Apache), making the comparison unfair.</li>
622
- <li>Be sure to start Phusion Passenger Standalone with the <code>builtin</code> engine. This is the default.</li>
623
- </ul>
624
- </li>
625
- <li>Configure Phusion Passenger to <a href="#minimizing_process_spawning">use a static number of processes</a>. The number of processes should be a multiple of the number of CPU cores.</li>
626
- <li>Ensure that your app outputs HTTP caching headers, so that Phusion Passenger's <a href="#turbocaching">turbocaching</a> can kick in.</li>
627
- </ul>
139
+ <p>This documentation has moved. Please visit <a href="https://www.phusionpassenger.com/library/config/optimization/">https://www.phusionpassenger.com/library/config/optimization/</a></p>
628
140
 
629
141
 
630
142
  <footer>