Search code examples
phpnginx

PHP-FPM its anatomy


Since PHP-fpm wiki is down and different sources tell me to do different things i decided to post it here and clarify few things

PHP-FPM compiles and executes the PHP script, sending the output back to the web server.

Currently i am using nginx as a proxy server, the plan is to send all request that require dynamic content to PHP-fpm from nginx. And question immidiatly raised, can i have multiple machines running php-fpm ? (scaling and stuff), answer i found bellow.

Although requests pass via a proxy connection, the PHP-FPM service must run on the same server as the web server. @inmotionhosting.com

Which sounds like a logical thing since i am passing $document_root param for it to load php files from.

My question is: How exactly php-fpm locates the file it needs to execute ? what other params i can pass


Solution

  • Yes, you can have multiple machines running PHP-FPM. This implies that you have to synchronize the files between the instances.

    PHP-FPM service must run on the same server as the web server

    The statement is not really correct. Web server can be on one machine, and a PHP-FPM instance can be on the other. PHP-FPM can listen on a network socket(port) in this case. And as long as web server (NGINX), tells PHP-FPM the filename to render that exists on the PHP-FPM server, it can get the response from it, and render for the client. This makes sense for scaling.

    For single server setup (no scaling), you'd have a standard setup of everything on the same server; and PHP-FPM bound to / listening on a UNIX socket, and not network.

    PHP-FPM is a FastCGI server so it's supposed to follow the protocol. It doesn't really locate anything, this is what NGINX does. Once it did, it then passes the located filename in SCRIPT_FILENAME parameter/environment variable, while talking to PHP-FPM; that is among few other parameters

    To influence how NGINX locates the files, you can use the directives:

    • root
    • rewrite
    • alias
    • index
    • fastcgi_param

    E.g. say we have a standard "front-controller" website written in PHP. The following is NGINX config essentials used by it:

    root /var/www/html;
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }
    location ~ \.php$ {
        include fastcgi_params;
    }
    

    What happens when visitor hits /foo/bar URL?

    • NGINX looks at the longest prefix-based location, which is / and chooses it for current request
    • It also checks for any regex locations but finds none that match to the URI
    • So it attempts to actually see if there is root directive's value + /foo/bar file on its system. That is, it checks using a stat system call, whether /var/www/html/foo/bar exists. If the file indeed exists, it will just serve it
    • If the file does not exist, then NGINX attempts to see if /var/www/html/foo/bar/ directory exists. It it does, then NGINX will check the existence of files defined by index directive (e.g. index.html) in a defined order, and use those to satisfy requests (if they do exist), e.g. /var/www/html/foo/bar/index.html
    • If those do not exist, NGINX finally knows it needs to serve using /index.php. How the try_files works is that "reaching" its last argument will result in another location search, and this time it will match the regex location of \.php$.

    That's where the magic of talking to PHP-FPM will happen, as in NGINX will pass on the script filename which is constructed off root and current, internally rewritten request URI. How it is constructed can be configured using the ngx_http_fastcgi_module nginx module directives which are documented here