Notice: This solution only works if NGINX and PHP-FPM both reside on the same server.
A ‘git pull’ on a live server for deployments isn’t ideal since all files don’t change on the disk at the same millisecond. A request that starts on one version of the code might access other files which could be updated during the request. To get truly atomic deployments, PHP deployment applications like Capistrano have a symlink pointing to the current build and simply update the symlink to the new build once the new build folder is ready. Since Linux doesn’t itself have any disk cache, changing the symlink to point to the new build is atomic. At the same millisecond, all files in the symlinked folder now point to their newer versions.
This build process has some issues.
The setup:
1) NGINX(the web server) and PHP-FPM(PHP FastCGI process manager) both reside on the same server.
2) NGINX serves from the document root(/var/www/app.com) which is a symlink to the current build.
2) Visitor requests https://app.com/hello.php. Nginx proxies PHP-FPM and asks it to execute /var/www/app.com/hello.php. PHP-FPM returns output of the above script to NGINX and NGINX serves it back to the visitor.
3) PHP Opcache is a cache with maintains a mapping of (script path -> machine code translations). This cache prevents interpreting PHP code again and again and makes a lot of difference in performance.
4) PHP’s Realpath Cache is a cache containing path mappings for relative file includes within PHP scripts. It also makes a lot of difference in performance if a lot of ‘require/require_once’ and ‘include/include_once’ statements are used in the scripts.
The problem
The last step in the build process is changing the symlink. On changing the symlink, FPM was still executing PHP scripts from the old build folder.
Continue reading “Truly atomic deployments with NGINX and PHP-FPM” →