Warming-Up Kentico in Azure Cloud Services

   —   

Azure Cloud Services continues to be a great option for times when companies want to add an additional level of control over their applications when deploying to the cloud. With this model, developers package their applications and server configurations and then push them to Azure storage. From there, Microsoft creates a new server based on the configuration, then deploys the application. This process automates many of the administrative tasks and allows the developer to solely focus on their own sites.

When deploying Kentico to this platform (or nearly any other cloud platform), there is an initial hit to performance as the site is compiled. This can result in a delayed initial response to the first request to the site. Luckily, Azure Cloud Services offers some functionality to reduce this hit. In this blog, I’ll show you how to warm up your sites when deploying Kentico to Microsoft’s PaaS platform.

Background

For this article, my explanation is based on deploying a standard Kentico application to Azure Cloud Services. As with any other Kentico deployment, deploying to Azure PaaS results in a compilation of the site, a process that may delay the initial response for 30+ seconds for complex applications. My main goal in this process is to reduce the initial request time when a user accesses the site after deployment. In order to accomplish this, I leverage a few cool features of cloud services and IIS to improve the overall user experience when accessing the application.

You can read more about Running Kentico on Azure in our document here.

IIS8 Application Initialization Startup Task

With IIS8, Microsoft introduced the Application Initialization functionality. This feature allows the AppPool to be started as soon as IIS is reset so that it is always ready to accept requests. This reduces the amount of time the initial request takes because the pool is already in a running state.

You can read more about IIS 8 Application Initialization here.

In order to leverage this from within our Cloud Service, I need to install this feature into the OS. I can do this by using a Startup Task to execute the command that installs the feature.

I put the following code in a .cmd file to be executed when the role starts.

PKGMGR.EXE /iu:IIS-ApplicationInit

In my ServiceDefinition.csdef file, I configure the startup task to be executed in “elevated” mode.

    <Startup>
      <Task commandLine="PrecompileInit.cmd" executionContext="elevated" taskType="simple" />
    </Startup>

Another small change is to make sure that the web role runs in “elevated” mode. This allows the code to access the necessary system files to complete the command. In the ServiceDefinition.csdef file, I add the Runtime executionContext setting.

  <WebRole name="CMSApp" vmsize="Standard_D1">
    <Runtime executionContext="elevated"></Runtime>

You can download the .cmd file below.

Download PreCompileInit.cmd

AppPool Configuration in Role

After installing the IIS8 Application Initialization feature, I can configure the AppPool to be in the “Always Running” state. Additionally, I will set the “preloadEnabled” flag to true. This option will cause initial requests to the site to occur as soon as the role is online. This will initiate the compilation of the site when the role is brought online, and eliminate situations where the user experiences the delay.

In my WebRole.cs file, I add the following code to the OnStart method.

public override bool OnStart()
{
    RoleEnvironment.Changing += RoleEnvironmentChanging;
 
 
    using (var serverManager = new ServerManager())
    {
        var mainSite = serverManager.Sites["CMSApp_IN_0_Web"];
        var mainApplication = mainSite.Applications["/"];
        mainApplication["preloadEnabled"] = true;
        var mainApplicationPool = serverManager.ApplicationPools[mainApplication.ApplicationPoolName];
        mainApplicationPool["startMode"] = "AlwaysRunning";
 
        serverManager.CommitChanges();
    }
 
    return base.OnStart();
}

This code will loop through all of the applications deployed on the role and set their AppPool properties to the desired values. This can be helpful if your deployment includes more than one application.

Testing

Now that those two pieces are in place, I can deploy my changes and test the system. Once the initial deployment is done, I use RDP to view the role and then view the CPU utilization.

CPU Utilization

This shows me that the IIS worker role is immediately being called, and the site is compiling, based on the large CPU utilization.

I can also see the Temporary ASP.NET files being generated because the initial request is complete on the server.

Temp ASP.NET Files

Once the compilation is complete (and the CPU usage goes down), I wait until the role shows “Online” in the Azure Management Portal. Once this happens, I can access the site.

Home Page

From the debug information, you can see the entire request took 3 seconds to complete. This tells me the site did compile and leverage the “warmed-up” version for the request. This was offloaded to the server, and a user would not have to wait as long to view the site.

Page Load Time

Moving Forward

As you can see, warming-up the site can have a significant impact on performance and usability. Any new site will have this initial delay; however, by using the method above, you can hopefully minimize the impact on your users by offloading that processing onto the server. This will result in an overall better experience and more consistent site performance.

In addition to the above method, you can do a number of other things to warm up your sites when deploying.

These are:

  • Setting the AppPool to not recycle using a startup task.
  • Leveraging Azure Endpoint monitoring to access your site every few minutes.
  • Writing custom code in your OnStart method to access more areas of your site.

I hope this article helps you to deploy your sites more easily. If you have other ideas, please share them in the comments.

Good luck!

This blog is intended for information purposes only and provided an example of one of the many ways to accomplish the described task. Always consult Kentico Documentation for best practices and additional examples that may be more effective in your specific situation.

Share this article on   LinkedIn

Bryan Soltis

Hello. I am a Technical Evangelist here at Kentico and will be helping the technical community by providing guidance and best practices for all areas of the product. I might also do some karaoke. We'll see how the night goes...

Comments