Search code examples
phpnginxfpm

How can I configure NGINX + PHP5-FPM to reserve connection slots for a specific IP range?


During some rare peak usages, my server runs out of available PHP5 FPM available children (I can't increase this number further without risking running out of memory). It is somewhat acceptable to me if an end user receives a 503 or 504 message in a rare case, but there are specific clients API requests to my server that I'd like to make sure are always accessible to certain IP address ranges.

Is there any way for me to specify a limit on fastcgi pass through requests from certain IP ranges, and then allow an additional 5-10 "reserved connection slots" for requests from another IP range? This is sort of what I'm thinking:

php5-fpm max children: 100
max fastcgi connections for standard IP range: 90
max fastcgi connections for "priority" IP range: 100

Essentially reserving those last 10 child processes for certain clients.

I was thinking of trying to use worker_connections / worker_processes for these limits, but with their context being events is there no way to have them vary by request IP?


Solution

  • You can add another pool, and configure nginx to use it for reserved IPs. The downside is clients from this IP range couldn't use the "common" pool which might not be acceptable in some usecases.

    Basically, if you copy:

    cp /etc/php5/fpm/pool.d/www.conf /etc/php5/fpm/pool.d/www-special.conf   
    

    change the socket:

    sed -i 's/listen = \/var\/run\/php5-fpm.sock/listen = \/var\/run\/php5-fpm-special.sock/g' \
        /etc/php5/fpm/pool.d/www-special.conf
    

    and adjust pm.max_children to 90 and 10 in each file:

    sed -i 's/pm.max_children = .\+/pm.max_children = 90/g' \
        /etc/php5/fpm/pool.d/www.conf 
    
    sed -i 's/pm.max_children = .\+/pm.max_children = 10/g' \
        /etc/php5/fpm/pool.d/www-special.conf 
    

    you can use new pool for the selected range of IP in nginx config (don't forget to restart service php5-fpm restart).

    E.g. with geo module, you can define $socket in /etc/nginx/conf.d/geo.conf as:

    geo $socket {
        default unix:/var/run/php5-fpm.sock;
        10.0.0.0/8 unix:/var/run/php5-fpm-special.sock;
    }
    

    And then update fastcgi_pass directives to use it:

    sed -i 's/fastcgi_pass unix:\/var\/run\/php5-fpm.sock;/fastcgi_pass $socket;/g' \
        /etc/nginx/sites-available/default