A single php-fastcgi process blocks all other PHP requests

5,705

Solution 1

Found the answer at: https://stackoverflow.com/questions/598444/how-to-share-apc-cache-between-several-php-processes-when-running-under-fastcgi/1094068#1094068

The problem isn't PHP, but mod_fcgid. While PHP spawns multiple children, mod_fcgid is ignorant of it, and will serve one request per child. Hence, when FcgidMaxProcessesPerClass 1 is used, all PHP execution happens after each other. *

The solution presented at which links to: http://www.brandonturner.net/blog/2009/07/fastcgi_with_php_opcode_cache/ explains how to use mod_fastcgi which doesn't have this limitation. It will send multiple requests to the same child.

[*] Note that not using FcgidMaxProcessesPerClass 1 results in many separate instances of PHP, ruby, etc.. while they are all capable of processing many requests internally in a single process.


Hence a new Apache config to use PHP with fastcgi:

<IfModule mod_fastcgi.c>

    # Needed for for suEXEC: FastCgiWrapper On
    FastCgiConfig -idle-timeout 20 -maxClassProcesses 1 -initial-env RAILS_ENV=production
    FastCgiIpcDir /var/lib/apache2/fastcgi

    AddHandler php5-fcgi .php
    Action php5-fcgi /.fcgi-bin/php5-wrapper.sh
    DirectoryIndex index.php

    ScriptAlias /.fcgi-bin/ /srv/www/cgi-bin/
    <Location "/.fcgi-bin/php5-wrapper.sh">
        Order Deny,Allow
        Deny from All
        #Allow from all
        Allow from env=REDIRECT_STATUS
        Options ExecCGI
        SetHandler fastcgi-script
    </Location>

    # Startup PHP directly
    FastCgiServer /srv/www/cgi-bin/php5-wrapper.sh

    # Support dynamic startup
    AddHandler fastcgi-script fcg fcgi fpl
</IfModule>

Solution 2

First, your wrapper script and setup is Just Plan Wrong in a bad way, unless Apache's docs are out of date. Read the "Special PHP Considerations" in the mod_fcgid docs and use the script and example settings there. Your current setup will basically spawn a bunch of unusable php child processes, then every 5001st PHP request will error out since PHP will exit after the 5000th request, but you are missing the FcgidMaxRequestsPerProcess 5000 directive that tells mod_fcgid that it will need to start a new PHP process after 5000 requests.

As for simultaneous PHP processes, each simultaneous request requires it's own PHP process, so you will need to increase your FcgidMaxProcessesPerClass directive to a higher number.

Share:
5,705
vdboor
Author by

vdboor

Software/web developer with enthusiasm for technology and insight in the Open Source world. Driven to create the best out of technology, solving things in a proper way, and creating products which prove to be a real benefit for the customer.

Updated on September 18, 2022

Comments

  • vdboor
    vdboor almost 2 years

    I've recently switched to a FastCGI setup for PHP (Apache2-worker and mod_fcgid). However, when a single PHP script is very busy, it seems to block all other PHP requests. What would be wrong with my configuration?

    My main reason for using mod_fcgid is to keep PHP memory usage under control. With mod_php, all individual Apache forks grow in memory after serving PHP.

    I've also switched to the apache2-worker model, since there all thread-unsafe PHP code exists outside Apache.

    My FastCGI script looks like:

    #!/bin/sh
    #export PHPRC=/etc/php/fastcgi/
    export PHP_FCGI_CHILDREN=5
    export PHP_FCGI_MAX_REQUESTS=5000
    
    global_root=/srv/www/vhosts.d/
    exec /usr/bin/php-cgi5 \
    -d open_basedir=$global_root:/tmp:/usr/share/php5:/var/lib/php5 \
    -d disable_functions="exec,shell_exec,system"
    

    My Apache config looks like this:

    <IfModule fcgid_module>
      FcgidIPCDir /var/lib/apache2/fcgid/
      FcgidProcessTableFile /var/lib/apache2/fcgid/shm
      FcgidMaxProcessesPerClass 1
      FcgidInitialEnv RAILS_ENV production
      FcgidIOTimeout 600
      AddHandler fcgid-script .fcgi
    
      FcgidConnectTimeout 20
      MaxRequestLen 16777216
    
      <FilesMatch "\.php$">
        AddHandler fcgid-script .php
        Options +ExecCGI
        FcgidWrapper /srv/www/cgi-bin/php5-wrapper.sh .php
      </FilesMatch>
      DirectoryIndex index.php
    </IfModule>
    
  • vdboor
    vdboor almost 13 years
    When I kill the php-cgi5 process, it's just recreated, so that doesn't seem to happen. Currently PHP manages it's children, instead of mod_fcgid doing that. I'll still try out your suggestions, see how that works!
  • Philip Durbin
    Philip Durbin about 12 years
    great answer! see also whorka.github.com/blog/2012/02/08/…