mod_fcgid

While fiddeling around with mod_fcgid it turned out I have no clue what the settings mean. And they aren’t very good described. Well maybe they are and I’m just not fit enough to get the correct definitions. So I asked Sven…

The definition for fastcgi-server is unclear to me. Basically I understood it as „server-process“ which is in my case a wrapper-script/php. Such a fastcgi server, can serve many requests and thus has child-processes.

Keeping this in mind and taking a look at IdleTimeout we’re talking about the time a fast-cgi-application was idle and so didn’t receive any request. The important part about this setting is, that starting a new fast-cgi-application takes more time. If a user visits your website and there is no fast-cgi-application running, he/she will have a little delay. Opening another page on your website will go fast. So, you’re dealing here between performance and resources. The earlier the process is terminated, the more resources you have available for other things. The later the process is terminated, the higher the chance to serve a user with no delay.

I’m not sure how to determine a good value for this setting. Probably taking a look at all logs and determining the average time between initial requests could be used. For example: If you’re receiving new requests all 10 minutes, a setting of 11 minutes might make more sense than a setting of 5 minutes. If you’re receiving new requests every minute an even shorter value _might_ make sense. The default value for IdleTimeout is 300 seconds, which means 5 minutes. It just depends a lot on the scenario. For example: A page with high traffic and lots of visitors might want to higher idletimeout and other timeouts to make sure that the server doesn’t have to start thousands of new fast-cgi-applications/processes <- that might be end up in extreme slow downs. In another scenario, on a vserver with limited resources where you get visitors every 30 minutes you might want to limit the timeouts to save resources. So, it really depends on your use-case. Also, another note about this: It might make sense to set max_execution time in php to 0 and just use the IdleTimeout Feature of the fast-cgi-server. One might think that the fast-cgi-stuff uses the cli, and due to that max_execution time would be 0 per default, my tests have shown that this is not true (at least not with mod_fcgid, php 5.2 and ispcp). So - The max_execution time needs to be highered to match the IdleTimeout. Now there's also BusyTimeout which is there to define how long a single-request can keep a fast-cgi-application busy. That’s by the way where my confusion starts. The documentation says it terminates the process. Which one? The child process or the server one? Of course it wouldn’t make much sense to terminate the whole fast-cgi-application because of a single-request (if that application has child processes or is able to handle many requests simultanously) – But how could I know? It’s not documentated. Let’s assume, this defines the maximum time a single-request (child process) can run. In this case, if your fast-cgi-application is PHP the same or a similar value to your php.ini’s max_execution time would make sense. Example: The default max_execution_time of PHP is 30 seconds. The default BusyTimeout of fcgid is 300 seconds. Thus a single-request is always finished or „over“ after 30 seconds. Doesn’t make much sense to allow 300 seconds then – In this case 31 or 32 would be a good value. BusyScanInterval is similar. That setting scans processes every 120 seconds, while our PHP script is already finished after 30 seconds – It will never each BusyTimeout or BusyScanInterval.

Personally I think max_execution time of 30 seconds is not enough for a php-script, Sven’s opinion is different here: Uploading large files through PHP is inefficient (which is true) and then 30 seconds is of course enough for a normal website. Uploads should be handled by the webserver directly. A good value for Busy* should match the runtime of your fast-cgi-server, in case of php’s default value, 30 seconds. With a check every 14 seconds.

You could tune max_execution time by the way, by taking a look at your max upload size. Let’s assume that the average user of your website (who is allowed to upload) got a 3mbit/s connection:

100 mbit/s = 11 MB/s (yeah ppl argue, might be 10, might be 12)
1 mbit/s = 11 / 100 = 0.11 MB/s
3 mbit/s = 0.33 MB/s

In 30 seconds you can upload 0.33*30 MB with a 3mbit/s connection. That’d be 9.9 MB. Keeping this in mind, it might make no sense to define a max upload size of 100 MB – As your users can’t reach that within 30 seconds (except they’ve got a quite good connection). However, look at this calculation sceptical – It should just give an idea on how to tune your parameters.

And finally there’s ProcessLifeTime which is meant to terminate the whole fast-cgi-application regardless of whether it is busy or idle. This is a good thing to avoid having processes eating up all memory and similar things, because the application will be „refreshed“ each x minutes. That means, ProcessLifeTime should be a multiple of IdleTimeout.

Apart from BusyScanInterval there’s also IdleScanInterval. Basically you can choose how frequently to „check“ the specific process for, whether it is idle or busy. The more frequently you check, the more accurate the decission might be. Per default it’s about two checks. The checks should be smaller than the amount of their parent setting. For example: BusyTimeout of 30 and BusyScanInterval 60 makes no sense. Minimum value would be 29. If you want to check twice in it’s run-time you’d set 29/2 = 14 (rounded down) – The first check happens after 14 seconds, the second check happens after 28 seconds. So basically: (*TimeoutValue – 1) / AmountOfChecks = Interval

Then there is ErrorScanInterval and ZombieScanInterval. You can choose between scanning very frequently (might eat resources/slow things down) and terminating processes faster (which might free resources earlier and give faster-responses on errors). I think a good value is between 3 and 9 seconds.

One of the most interesting settings is DefaultMinClassProcessCount with a default value of 3. Which avoids the termination of idle-processes in some circumstances. It will kill only idle-processes if there are more than 3. Which is again confusing, are processes of a fast-cgi-application or all fast-cgi-applications of the webserver meant? However, I assume, that a fast-cgi-application handles many requests which turn into child-processes and that such childs are meant with „processes“. Right after tuning IdleTimeout it makes sense to set this to 0 to always enforce the use of IdleTimeout.

And then there’s the trouble-causing (or more precisely the trouble-solving) setting PHP_Fix_Pathinfo_Enable. Usually you should set this to 1 only, if you got ;cgi.fix_pathinfo=1 in your php.ini. As you can see at the ; it’s commented in mine. Still it seems to be in-use. If I don’t use PHP_Fix_Pathinfo_Enable 1″ for mod_fcgid – Some Uploads are broken. Uploading a picture with more than 100kb results in 500 HTTP Errors which aren’t tracked by PHP or Apache Error log. Might be some PHP, Debian or mod_fcgid bug. I cannot track this issue down (Maybe I don’t want to investigate more time :p)

Finally there’s MaxRequestsPerProcess. Okay.. Errm. Probably I should just forget about server, childs, parents, processes, requests, and all this crap (In this case, I guess they mean, how many „requests“ a single-fast-cgi-server can handle).

Another problematic part is MaxRequestLen which was set to 1 GB with earlier versions and which is set to 128kB. According to the documentation, „only“ the header is meant – Not the message/content itself. However, I noticed errors with that low amount and so I’ve set MaxRequestLen to exactly the same value, people are allowed to upload in PHP. So if your max upload size in PHP is 10 MB, set MaxRequestLen to 10*1024*1024 (10 * 1024 * 1024) which would be 10485760 bytes.

There are a few other parameters which might be worth to look at, however – The above stuff is enough for me to tune.

A few further links. I’ve checked them and couldn’t find anything bad on those pages, however, I cannot give any guarantee for that – So click the links below on your own risk (you’re leaving this page by clicking such a link)

And thanks to Sven for helping a bit 🙂

No Comments

Post a Comment