FastCGI on Modern DirectAdmin

My datacenter have now agreed to configure suphp and FastCGI on my new server. Is there a way for a beginner like me (with limited knowledge of this) to be able to check wether FastCGI actual is setup (and not only CGI) on my server? This so that I afterwards can check this after the technician at the datacenter say they have completed the job?
 
Yes there is, a simple one really. The output of "pstree -u" and "pstree -up" should contain something similar to those snippets:
Code:
$ pstree -u
[...]
     ├─httpd─┬─httpd(apache)───65*[{httpd}]
     │       ├─httpd(apache)
     │       └─httpd(apache)─┬─php-cgi(webapps)───128*[php-cgi]
     │                       ├─php-cgi(tillo)───128*[php-cgi]
     │                       ├─php-cgi(noirgame)───128*[php-cgi]
     │                       ├─php-cgi(lithium)───128*[php-cgi]
     │                       ├─php-cgi(exty)───128*[php-cgi]
     │                       ├─php-cgi(drunkard)───128*[php-cgi]
     │                       ├─php-cgi(psyastro)───128*[php-cgi]
     │                       └─php-cgi(vito)───128*[php-cgi]
[...]
Code:
$ pstree -up
[...]
        |              |                     |-{httpd}(14831)
        |              |                     `-{httpd}(14832)
        |              |-httpd(30625,apache)
        |              `-httpd(30626,apache)-+-php-cgi(3839,webapps)-+-php-cgi(3840)
        |                                    |                       |-php-cgi(3841)
        |                                    |                       |-php-cgi(3842)
[...]

You can see clearly that there are 8+8*128 persistent php-cgi processes, a master and 128 handlers for each web user on my server. The exact number depends on the setup of course.

I added the second snippet to show you how to check that they are persistent: the PID must always be the same (they will eventually change on respawn, when needed, or Apache restart). For example, 3839 is the PID for my webapps's master process.

FastCGI offers the possibility to respawn the master and handlers processes from time to time in order to exit from a stale PHP state in case of a bug, but don't let it do too much often: it would recreate the performance loss between mod_php and CGI, because processes take time (and IO+CPU load) to spawn.
On my setup I never let any process respawn, and I never had any problem.
 
Last edited:
Thank you so much, Tillo! It is reassuring that I afterwards can check this myself.
 
Hello. I am Polish with poor english, so sorry for grammar errors ;)

I doing step-by-step instructions from it: http://www.tillo.ch/temp/fastcgi.txt , skipping settings for php4. I have some troubles with suPHP and virtual_hosts.conf, but finally all errors go away :)

Unfortunately, i can't run any php script: pages is "loading..." a long time, and finally I get "500 Internal Server Error"...

This is my configs, listed like "fastcgi.txt":
Code:
x-wing:~# cat /etc/httpd/conf/extra/httpd-phpmodules.conf
#LoadModulesuphp_module/usr/lib/apache/mod_suphp.so
LoadModule      fastcgi_module          /usr/lib/apache/mod_fastcgi.so

x-wing:~# cat /etc/httpd/conf/extra/httpd-includes.conf 
# All FastCGI directives
Include conf/extra/httpd-fcgi.conf

x-wing:~# cat /etc/httpd/conf/extra/httpd-fcgi.conf 
<IfModule mod_fastcgi.c>
ScriptAlias /fcgi5 /opt/fcgi/php5.fcgi

<Directory "/opt/fcgi">
AllowOverride None
Options +ExecCGI -Includes
Order allow,deny
Allow from all
SetHandler fastcgi-script
</Directory>

AddHandler fastcgi-script .fcgi

FastCgiIpcDir /tmp
FastCgiWrapper /opt/fcgi/suexec
FastCgiConfig -maxClassProcesses 1 -maxProcesses 16 -processSlack 1 -idle-timeout 300 -pass-header HTTP_AUTHORIZATION

AddType application/x-httpd-php5 .inc .php .cphp .phtml .php5

Action application/x-httpd-php5 /fcgi5

</IfModule>

x-wing:~# ls -la /opt/fcgi
total 36
drwxr-xr-x 2 root root  4096 Feb 17 22:52 .
drwxr-xr-x 3 root root  4096 Feb 17 22:29 ..
-rw-r--r-- 1 root root   170 Feb 17 22:34 php5.fcgi
-rwsr-xr-x 1 root root 24080 Feb 17 22:52 suexec

x-wing:~# cat /opt/fcgi/php5.fcgi 
#!/bin/sh
PHPRC="~"
export PHPRC
PHP_FCGI_CHILDREN=256
export PHP_FCGI_CHILDREN
PHP_FCGI_MAX_REQUESTS=50000
export PHP_FCGI_MAX_REQUESTS
exec /usr/local/php5/bin/php-cgi

x-wing:~# /usr/local/php5/bin/pecl list
Installed packages, channel pecl.php.net:
=========================================
Package Version State
APC     3.0.19  stable

x-wing:~# tail -n 6 /usr/local/etc/php5/cgi/php.ini
[APC]

extension=/usr/local/php5/lib/php/extensions/no-debug-non-zts-20060613/apc.so

apc.shm_size = 128
apc.filters = "sql_.*\.php"

Code:
x-wing:~# pstree -u
init-+-atd(daemon)
     |-cron
     |-da-popb4smtp
     |-directadmin(nobody)---5*[directadmin]
     |-dovecot-+-dovecot-auth
     |         |-16*[imap-login(dovecot)]
     |         `-16*[pop3-login(dovecot)]
     |-exim(mail)
     |-httpd---6*[httpd(apache)]
     |-init-logger
     |-mysqld_safe---mysqld(mysql)---9*[{mysqld}]
     |-named(bind)---4*[{named}]
     |-portmap(daemon)
     |-proftpd(ftp)
     |-rsyslogd---3*[{rsyslogd}]
     `-sshd-+-sshd---bash
            `-sshd---bash---pstree

I have no idea what is wrong?
 
First thing I see is that php5.fcgi doesn't have the executable bit. Run "chmod +x /opt/fcgi/php5.fcgi". This may be the main problems, but check Apache and PHP errors logs to be sure.

Also, make sure that when you run "/usr/sbin/httpd -M" there is "fastcgi_module". If there isn't, the path may be wrong or the module may not be compiled correctly. Again, check in the Apache errors log.

Same thing with the APC module, once you get PHP running check with the apc.php file (laying somewhere in your system, copy it into a public_html directory) that APC is loaded and working.

Finally, I specified (outside the fastcgi.txt, but in every post where I refer to it) you should run the worker MPM and you are using the prefork MPM (the Apache handlers are processes and not threads). I'm not sure this will prevent FastCGI from working but there is absolutely no reason to stick with the prefork MPM since you don't use mod_php anymore, and it's a huge performance killer.
 
Yes, chmod was a problem. I try rebuild apache with "worker MPM". I think it's will work quite good, but... without any warning all memory was filled out and I now waiting for admin to restart server...
 
Yeah, in fact in your conf I see that you run 256 handlers per user, and each master process uses up to 128MB of memory for APC.

Now, on my system, after a while every PHP handler uses up to 20MB of memory for my busiest user.
If you take this into consideration, and say you have 20 users, this makes:
20*128MB + 20*256*20MB = 2'560MB + 102'400MB = 104'960MB = 105GB of RAM needed.
Of course this is the worst case of all, your PHP handlers may use less than 3MB each (as for my idlest user) and you may have less than 5 users, do the math.
 
So how I should set that values if I have only 2 GB of RAM?

5*32MB + 5*64*5MB = 160MB + 1'600MB = 1'760MB ~= 1.7GB?
 
If you have 5 users, that's right. Take into account that "webapps" is one of them, so you should have 4 customers.

Since you probably use the same server for other things (like MySQL) and you may want to spare some RAM (unless you want to suffer from easy DoS), this may be better:

5*128MB + 5*16*5MB = 640MB + 400MB = 1040MB = ~1GB

As you can see I gave more memory to the APC opcode cache instead of to the PHP handlers; that's because it's better to have a consistent cache and spawning some processes than the opposite.
Additionnally, if none of your customers have more than 16 users at the same time no handler will be respawn anyway.

I feel like explaining a little how the PHP handlers are used by FastCGI.
- when you set PHP_FCGI_CHILDREN to 16, that will be the number of handlers per user instantly spawned
- when you set PHP_FCGI_MAX_REQUESTS to 50000, that will be the number of requests an handler will serve before getting automatically respawn, to avoid memory leaks (that's why I have 20MB on each handler, because I set it to 0: they never respawn)
- when the requests are more than PHP_FCGI_CHILDREN, a multiple of that is spawned automatically to avoid denial of service, and they will last until they are being used (if at a given moment 17 users are querying a user's website, for a little while you will have 16 more handlers for that user; in my tests, a new APC memory segment will be used for them!)
 
Ok, I am understand part of this black magick... ;)

I have discovered that I have only 1 GB of RAM... So, I run htop (top) to check how many RAM is used.

On previous settings I had 750 MB used (when apache is stopped: 215MB)

I was change my settings to this values:
Code:
apc.shm_size = 64
Code:
PHP_FCGI_CHILDREN=16
Code:
<IfModule mpm_worker_module>
    StartServers          1
    ServerLimit           1
    MaxClients          32
    MinSpareThreads      16
    MaxSpareThreads      32 
    ThreadsPerChild      16
    MaxRequestsPerChild   0
</IfModule>

Now I have 378 MB used (about 30% of RAM).

Hmmm... My VPS have only a few small e-shops and websites, and I don't need super-performance, but I don't want a small DoS again...

How I should set it up, to gave a similar to default for DA peformance (RAM using)?
 
Well, the equivalent to DA default settings is CHILDREN=1, MAX_REQUESTS=1 and shm_size=0. But then, why would you want to use FastCGI?

I guess what you are trying to say is that you would like to know a minimal useful setting for a small system like yours, with not many users nor requests.

There it is: CHILDREN=4, MAX_REQUESTS=5000, shm_size=32.
For 5 users, this makes use of max 160MB for opcode cache and max ~100MB for all persistent handlers together, so a 260MB maximum RAM use by PHP. Less than that, FastCGI isn't really worth it.
 
Hi tillo, thank you for sharing your knowledge. Its very, VERY helpfull.

Base on that i finally run on my vps DA php + suexec + fastcgi. Unfortunelly i have not enought memory to handle all user by fastcgi.

I wonder if it possible to handle only selected user by fastcgi (and use op-cache for him/them) and other non-exacting users by suphp.

If it possible can you give me some clue how to do it?
 
It surely is possible, but I never did it.

You may try it like that:
- de-comment the line that loads the suPHP module within httpd-phpmodules.conf.
- move the "Action application/x-httpd-php5 /fcgi5" line from httpd-fcgi.conf into the correct VirtualHost within /usr/local/directadmin/data/users/<user>/httpd.conf.

This won't deactivate APC for the users running suPHP, so keep in mind that PHP may be slightly slower (the opcode cache won't be useful, but it will be created at each request anyway).
 
I would not use mod_fcgid if I were you. It's not compatible with PHP-FPM which is the future of PHP/FastCGI.
 
I would not use mod_fcgid if I were you. It's not compatible with PHP-FPM which is the future of PHP/FastCGI.

Never heard of PHP-FPM until today :D Anyway, how to use it? just compile PHP-FPM with PHP 5.3 and then, with FastCGI, it will be used automatically?

Also, just found this -> http://bugs.php.net/52569 that said

We are currently implementing PHP-FPM in a shared hosting environment. We have many users on one server (about 200) and we have to define one pool for each customer (each with a different uid).
If PHP-FPM starts one children per customer at startup, this would kill the servers, I think.
So we have to start them on demand. When using PHP via mod_fcgid/suEXEC you can define FcgidMinProcessesPerClass 0, which works fine, but in PHP-FPM this is not allowed.

I tried to remove the check in fpm_conf.c:
if (config->pm_min_spare_servers <= 0)
if (config->pm_start_servers <= 0)

but this does not really work (zero children are created at startup which is fine, but no child is created on request and the request hangs). I currently don't find the right entry point.

So, I might need to wait for them to fix this before try it :(
________
Lovely Wendie99
 
Last edited:
Hmmm...Just lost my long reply in a BSOD ;(
Will try again later...
Short answer is that it's easy to setup, but there are little gains compared to all the hype out there regarding the benefits of FastCGI, unless you're on NGINX...
One positive thing would be the fact that you can use one pool per user, but as you've mentioned, it can lead to problems.
Another is that you can offer custom PHP version to customers that need one (and are willing to pay for it).
 
Hmmm...Just lost my long reply in a BSOD ;(
Will try again later...
Short answer is that it's easy to setup, but there are little gains compared to all the hype out there regarding the benefits of FastCGI, unless you're on NGINX...
One positive thing would be the fact that you can use one pool per user, but as you've mentioned, it can lead to problems.
Another is that you can offer custom PHP version to customers that need one (and are willing to pay for it).

Thanks for information. I will have to try that soon. In fact, I have one server that has only one website installed. (Quite a busy server though.) Anyway, I have plan to buy a better server to replace it. Will try that before I move it :)
________
FIX PS3
 
Last edited:
After having done some more testing, I don't find it as reliable as mod_php, but it could be due to my config/test or the different caching systems that are in place. I get half broken pages sometimes.
Don't forget to move back to mod_fastcgi if you want to use PHP-FPM.
 
Last edited:
Back
Top