Improving performance with application initialization on Azure App Service (Windows)

Often, performance on a website isn’t what it needs to be. One way you can improve performance is to cache files to the local disk. On Azure App Service Web Apps, an application can access the local disk at D:\local\temp. This location is specific to each instance. Due to the nature of Platform-as-a-service, this location is not easily accessible to the user. However, the application has access to this location pro-grammatically. Moreover, many popular applications and frameworks have file caching as a default feature.

PHP, a popular programming language in the Open Source community, has several MVC Frameworks that include file caching. Frameworks such as Laravel, Symfony, CodeIgniter and many others. In these frameworks, the cache location can be set to the local disk on the VM rather than the storage.

An easy way to clear this cache is to restart the App Service Web App. However, this causes your application to go offline for some time. An alternate way to clear the cache is to utilize the AppInit module within IIS. The IIS AppInit module can execute a script on a W3WP process recycle. These recycles occur on restarts, application settings updates, scaling to new instances, etc. This is not a complete list and more information can be found online.

In this article, you will learn how to execute a script through an application settings update. This is not intended to be a complete solution as your use-case may vary. It is intended to show you how the AppInit module can be used within App Service Windows.

The solution has three components:

  1. Create an initialization page to be executed upon a recycle. This is the clear cache script.
  2. Set the initialization page in the web.config.
  3. Update an application setting to trigger the recycle

Here is a sample initialization page written in PHP:

<?php 
/***** File Location: wwwroot/appInit/maybeCacheClear.php
***** This script runs when the web app is recycled.
**************************************************************
You can lock the cache in two ways so it is not cleared on a recycle:
1) add the application setting 'cacheLock' and set the value to true
2) create a file, cache.lock, within this directory
******************/
if ( file_exists('cache.lock') || ("true" == strtolower(getenv('cacheLock'))) ) 
{
$message = "================================\n" . 'Time Stamp: '. date('m/d/Y H:i:s') ."\n" . "--------------------------------\n" . "Cache is locked. Cannot clear cache.\n" . 'Computer Name: ' .$_SERVER['COMPUTERNAME'] ."\n" . 'Instance ID: ' . $_SERVER['WEBSITE_INSTANCE_ID'] . "\n\n";
}
else {
//!!CLEAR THE CACHE!!
//<INSERT CODE HERE TO CLEAR CACHE>
$message = "================================\n" . 'Time Stamp: '. date('m/d/Y H:i:s') ."\n" . "--------------------------------\n" . "*** CLEARING CACHE***\n" . 'Computer Name: ' .$_SERVER['COMPUTERNAME'] ."\n" . 'Instance ID: ' . $_SERVER['WEBSITE_INSTANCE_ID'] . "\n\n";
}
// Write the contents back to the file file_put_contents('cache.log', $message, FILE_APPEND);

Now that the initialization page has been created, tie this into the web.config so it is executed on a recycle. Here is a sample snippet with the Application Initialization script configuration

<configuration> 
<system.webServer>
<applicationInitialization doAppInitAfterRestart="true" skipManagedModules="true">
<add initializationPage="/appInit/maybeCacheClear.php" hostName="mangeshnew.azurewebsites.net"/>
</applicationInitialization>
</system.webServer>
</configuration>

The last piece of the solution is within Application Settings. Here we will create a key named “cacheLock” with a value of “true”. This setting determines if the cache should be cleared or not. When the value is set to “true”, the cache is locked and will not be cleared. However, when set to “false” the cache is no longer locked and it will erase the cache from the local disk.

Now that web.config, cache clear script and Application Settings are in place, trigger a recycle by updating an Application Setting. If everything went well, you will see a message within cache.log. It should look like this:

That’s it! As simple as that. Once you’ve placed these components in place, you can utilize Application Initialization to clear cache from local instances. I hope this has helped your application design be more performant. Questions or comments? Please leave feedback below!