The majority of modern web-services should be accessible for users at all times. A common but often overlooked problem here is the process of project re-deployment (i.e. update), causing your application to go down or return errors until the operation is finished. This can be solved with a variety of tools like Capistrano, Fabric and others. However, these supplements often require additional time, expense, and specialist knowledge for being successfully integrated and configured properly (e.g. this may be performed through setting up multiple servers with a load-balancer in front of them; while the deployment is running on one server – it is excluded from the route list, after that other servers could be updated). Obviously, such an implementation is rather complicated and requires a lot of extra resources, thus a better method is needed.
Such a new solution was proposed for PHP applications, running on top of Apache, by founder of this programming language and, simultaneously, CirrusGrid technical advisor – Rasmus Lerdorf. As an actively used at Etsy, and, therefore, being a battle-tested approach, it was subsequently taken as the basis for Zero Downtime & Atomic Deployment feature in CirrusGrid. The main idea of this method rests on the following two points:
In such a way, the updated project files can be seamlessly deployed, while the initial code version continues working and handling users’ sessions. And when the deployment is fully completed, the symlink instantly switches to the most recent version of the successfully deployed app, starting to redirect all the incoming requests to it. All of these together makes the deployment process fully atomic and implicit for your customers, simultaneously relieving you from performing plenty of envisioned manual operations.
Note: The availability of this functionality depends on your hosting provider’s settings.
Below, we’ll explore this mechanism in more detail by describing:
So, let’s go on!
First of all, we’ll consider more specifically how the above described PHP zero-downtime deployment mechanism actually works on CirrusGrid – let’s examine all of these processes step-by-step with a real example.
1. To start with, you’ll need a PHP environment (either a new or the already existing one) – we’ll use Apache for this example:
2. Next, proceed to the deployment of the required application. During this procedure, you need to tick the corresponding checkbox at the appropriate confirmation frame (depending on the project source type used) in order to enable the ZDT deployment option:
Note: While performing this for the first time for the already existing application, deployed to the ROOT context, all the previous data will normally be erased and overwritten with the “bare” app installation (for the deployment via archive/URL only).
3. During the initial deployment, a ROOT_timestamp (i.e. ROOT_year.mm.dd-hh.mm.ss) folder and a special ROOT file as a symlink to this folder are created inside the webroot directory of your application server.
As normal, the application is ready to handle requests just after the deployment process is finished.
If navigating inside the ROOT directory, circled above, the content of the currently used application version will be viewed, i.e. it is changed each time the symlink is switched.
This can be clearly seen if entering your application server’s container via SSH and executing the long format file-listing command for your webroot folder, i.e.:
ls -l /var/www/webroot
4. During the second deployment (i.e. when deploying an update), a new ROOT_timestamp folder is created – in such a way, the actual application version and customers, that are currently working with it, are not influenced.
Just after the new files are unpacked, symlink switches to this new folder, redirecting all the newly received requests to it. Herewith, the first folder is kept for processing the “old” users’ sessions (i.e. where handling started before the symlink switching).
Note: While updating an app version using archive/URL, all the comprised user-generated content (if there is any) should be manually moved to the newly created app directory from the older one, stored alongside (herewith, previously such an operation implies the full overriding of all the context data).
If using VCS, the app’s directory content is entirely copied (both tracked and untracked files), so no manual operations are required. However, we recommend to adopt the practice of the .gitignore list usage for the unnecessary files of your project, as this would save you some amount of resources and time during repetitive re-deploys.
5. All the following atomic deployments will be performed in the similar way. During each of them, the oldest project folder is removed, while a new ROOT_timestamp directory for the most recent project version is added.
In such a way, only 2 versions of deployed application – the latest and the previous one – are stored within an app server simultaneously (however, the older one can also be easily removed manually when it is no longer needed). This ensures no extra disk space consumption.
Note: If you’d like to avoid some project version from being automatically erased, just rename the corresponding folder before running the new deployment.
All of the operations are fully automated, thus no additional developer’s involvement is required, while the deployment itself is performed in a “soft” mode, i.e. even without app server restart needed and, as a result, without any application downtime.
Delving into the details of technical implementation, the atomic deployment option support at CirrusGrid is ensured by the following adjustments, applied to the corresponding PHP instances:
The appropriate functionality is handled with the help of the mod_realdoc module, which controls the abovementioned symlink switching. It can be additionally configured (if required) through the CirrusGrid dashboard within the conf.d > mod_realdoc.conf file.
Tip: Here, the RealpathEvery parameter defines the period of time for which the symbolic link path is stored and the frequency of its refreshing. It’s default value (0, as denoted within the code comments) was changed to 2 for ensuring all of the required operations (i.e. deployment and switching) to be completed before redirecting the requests to the new project version and as such, preventing the I/O slowdowns.This value can be easily changed to your custom one if needed (just do not forget to restart your app server node for its appliance). However, if using the ZDT deployment feature, we do not recommend to set it too high, as this would cause the delays in symlink switching.
For more information on this module’s specifics, visit its source page.
Here, atomic deployment is ensured by means of the in-built functionality with no additional modules inclusion – the corresponding settings can be found at the very end of the conf > nginx.conf file:
For now, as you know how all of this works, we can compare both classic and atomic deployment methods.
To prove the benefits of the ZDT update approach, a simple load test was run, with the following parameters as a basis:
So, let’s evaluate the results for both deployment methods with the simple statistics we’ve received.
Let’s start with the most commonly used variant of the project deployment, namely – classic, i.e. installation from a single archived package with no extra options like ZDT enabled:
As you can see, we actually get pretty good results:
Now, let’s perform the same test with the second competitor – ZDT. For a better comparison perception, we’ll keep the same color legend as before:
Response time remains stable and almost unchanged, but you can notice its slight enlargement during the update procedure, which is caused by the additional deployment process running alongside the serving of requests. Herewith, there isn’t even a single error during the whole test.
So, in such a way, we can assume that zero downtime deployment overcomes the problem of failed requests during application redeployment, simultaneously keeping the average response time on the same level. In addition, the atomic option leaves you a possibility to save all of the user-generated content, located inside the application directory, and easily move it to the new app’s version if necessary (while the classic method normally implies just the entirely new app version deployment).
You may also notice, that the minimum requests' handling time for the classic method is significantly lower than for the atomic one and, therefore, seems to bring better performance. But don’t be mislead, as it’s just a side effect of the failed requests presence (where serving time is also counted, despite it being not processed), while the average response time is almost the same for both methods.
Next, let’s repeat our test for the second CirrusGrid deployment type (i.e. if using Git/SVN repos) in order to find out whether ZDT retains its advantages in this case. And again we’ll start with the classic method:
As the deployment sources are placed at the remote resource, this will require a little more time compared to the installation from the already uploaded archive, which, actually, helps us to clearly see the difference. The response time now has a pretty long drop down (for nearly 4 seconds in our case), caused by the unavailability of the application (you can see that incoming requests start to fail at the same time – this is shown with a spike at the errors graph). Everything else remains similar to the previous deployment type.
Note: Unlike the archive deploy (where the old project is entirely removed before redeployment, which will always cause downtime), here the update procedure assumes changing of the differing files only. Therefore, you may not face any interruption in the service work if the files that are required to be changed, are currently unused.
Finally, the last test for the ZDT deployment approach via VCS also goes in line with our expectations by bringing a stable response time with its small incrementation during the simultaneous running of such operations as users’ sessions handling and project copying/updating.
At the same time, you can see that no errors appeared and all of the incoming requests are successfully processed.
Now, when you have all the information (both raw technical and visualized in graphs practical one) on the investigation and have seen how it’s easy to use the ZDT option within Jelastic PaaS, it’s time to summarize and make a conclusion on the key benefits it brings for your PHP app’s hosting:
In such a way, ZDT deployment usage makes updating of your projects completely painless and invisible to customers, helping you to get the most from your application!
Powered by BetterDocs
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.