Prelude

In the previous article, we went through the basic architecture of Apache and Passenger. Now I’ve been told that its a bit too much to digest in one shot but it’ll all make sense when all the 3 articles are read together. If not, you’re always welcome to drop a question in the comments section and I’d be happy to help.

Assumptions

In this article, we will be looking at the primary directives in Apache and Passenger for optimization. The rest of the series is specific to the case where a single RoR application is running on the server (say, TweakMyApp).

Apache Directives

The Apache directives that can be set for the pre-fork MPM are listed here with brief descriptions and suggested values.

StartServersThe number of child processes (workers) to start on Apache startup. The default 5 is good.

Apache will spawn child workers to handle multiple incoming requests. This directive specifies how many such child processes are required by default when Apache itself starts up. When Apache starts up, a main control process spawns the workers and is responsible for delegating requests to them. You can refer the previous article or the Apache docs for details about Apache’s achitecture.

MinSpareServersMinimum number of idle spare children to keep ready for expected requests. A high number is rarely good. Anything from 3 to 5 is fine.

Say this number is set to 3. This will tell Apache that even if there are no requests, keep at least 3 child workers alive for expected requests at all times.

MaxSpareServersMaximum number of idle spare children to keep ready for expected requests. Again, a high number is rarely good. Anything from 8 to 10 is fine.

Say this is set to 10. This tells Apache to keep at most 10 children alive to process expected requests. MaxSpareServers and MinSpareServers define a range of idle children to keep and Apache will kill or spawn children in order to stay within this range. These directives are important mainly to specify how much of your server’s memory is allowed to be hogged by Apache’s idle children.

MaxClientsMaximum number of child processes that will be launched to serve requests. The default of 150 is usually good.

One thing to remember in this directive is that, say one instance of TweakMyApp consumes 90MB of RAM, it does not mean that you are allowing (90*150) MB of RAM as the maximum request setting for the server. Apache processes consume much less memory than that. We will look at that in detail in the next post. Also, if you want to set this at anything above 256, then you need to tweak the ServerLimit directive first.

MaxRequestsPerChildSets the limit on the number of requests each individual child process will handle. Default of 0 (infinite) is perfect.

If you change this number, you give each child a finite number of actions before it will die. In effect, you are freeing memory by reducing the number of processes that are running when the server is not busy. Freeing memory for what? Maybe there are other applications on the server that could use the memory. But its not likely that they’ll require that extra memory only when the server is not busy. So leaving this setting at 0 is best, especially based on “our assumptions”.

Passenger Directives

The Passenger directives that are used for optimization are listed below with brief description.

PassengerMaxPoolSizeThe max number of RoR application instances that may run simultaneously.

This is the total number of application instances that the Passenger Application Pool will hold. Since we only have TweakMyApp running on our server, this number is essentially the number of instances of TweakMyApp we have ready in the Application Pool to server requests.

PassengerMaxInstancesPerAppThe max number of instances of each RoR application that may run simultaneously.

This is not relevant to us as we have only one application, TweakMyApp, to consider.

PassengerPoolIdleTimeThe max number of seconds for which an application instance can remain idle. This can be set to 0 (infinite) for our case.

This needs to be set at a finite value only if you have multiple applications. Say there is another application, IntrudingApp, that runs on the same server and needs another instance to serve incoming requests, and say TweakMyApp instances are sitting idle, then Passenger can shut down idle TweakMyApp instances and use the memory to spawn IntrudingApp instances. Since we only have TweakMyApp running and need it to be available at all times, 0 is perfect for us.

PassengerMaxRequests The max number of requests a given application instance will process. Again, this can be set to 0 (infinite) for our case.

This directive is very similar to the Apache MaxRequestsPerChild directive and is best left at 0 for us.

PassengerStatThrottleRateThe frequency with which Passenger should perform its file system checks. I’m leaving this at the default of 0.

This setting tells Passenger how often it needs to perform its filesystem checks like checking environment.rb and restart.txt . If you have an application that you dont intend to change much or one in which changes in the code can take effect slowly, then you might want to set this value to something higher. It will help free up some memory. But I’m leaving it at 0 here under the assumption that you have a highly dynamic application.

PassengerHighPerformanceThis setting increases Passenger performance at the cost of reduced compatibility with certain other Apache modules. Im going to go with the default of “off” here.

This setting improves Passenger performance but affects compatibility with other Apache modules like mod_rewrite and mod_autoindex. Im leaving this off to be on the safe side.

Passenger Global Queueing is another useful concept that could potentially speed up processing of requests further. Im leaving it off in my case because I have not tested it yet, but you could turn it o” at your own discretion. It is of special relevance if you are running multiple application on the server.

References

A similar, very useful blog post here

MaxClients and ServerLimit – Check the comments section here

The discussion in Passenger’s Google group

Check this discussion for more Passenger directives, highly recommend it

Global queueing discussion in Google groups

Multiple Apps

Most configuration for managing multiple applications on a server will be done using Passenger directives. For example, you may want to tweak the PassengerMaxPoolSize and PassengerMaxInstancesPerApp directives. There are other directives and concepts like Global Queueing also which can help you, but I’m going to point you to the Passenger Documentation for that.

In the next article, we will use what we have learnt so far to get to the nitty gritties – gathering metrics and tweaking configurations. Until then, ciao and feel free to drop in your comments.

Tags: , , , , , , ,

3 comments

  1. Great article..really concise content required for developers..just had a question as in how the combo Apache + Passenger handles error logging, both application level and system crashes?

Leave a comment