Slow Azure websites with Redis

During a load test of an Azure website, we noticed that the site started to become unresponsive when 10 concurrent users we loaded.

Session management has been utilized through a Redis cache. For anyone looking to use this I would recommend here as a good starting point.

Deploying the site locally using the live web.config transforms, we were able to run the following in the command line, to show all connections that were being made from the computer.

netstat -b

It was noticed that there were over 100 concurrent connections being made to the cache which stopped the site from being able to connect to the azure portal.

redisconnections_connectionerror

The azure portal had displayed the following recommendations to fix the portal

redisconnections_warnings

 

This was due to the concurrent connections being maxed out a 256 connections.

redisconnections_256

What was the culprit? Creating a new connection every time the class was instantiated.

It is recommend in the by MSDN to create a static instance of the connection that is shared across the application. This can either be achieved by using a singleton pattern, using dependency injection or by using the below code.

private static Lazy _redisConnection = new Lazy(() => 
ConnectionMultiplexer.Connect(<>));

This then happened.

redisconnections_10

 

Creating thumbnails from the front page of a PDF with ghostscript

Automation is such as wonderful thing.

  1. install Ghostscript to your computer. https://ghostscript.com/download/gsdnld.html
  2. Create a C# console app
  3. Copy the following code into your app and replace <<VERSION NUMER>> with your version number.
  4. Pass in the link to the PDF file, the folder name and the file name.
 public void PdfToJpg(string inputPDFFile, string outputImagesPath, string filename)
 {
     string ghostScriptPath = $"C:\Program Files (x86)\gs\gs<<VERSION NUMBER>>\bin\gswin32.exe";
     string ars = $"-dNOPAUSE -sDEVICE=jpeg -dFirstPage=1 -dLastPage=1 -r102.4 -o \"{outputImagesPath}\\{filename}.jpg\" -sPAPERSIZE=a4 \"{inputPDFFile}\"";
     Process proc = new Process();
     proc.StartInfo.FileName = ghostScriptPath;
     proc.StartInfo.Arguments = ars;
     proc.StartInfo.CreateNoWindow = true;
     proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
     proc.Start();
     proc.WaitForExit();
 }

Adding expire headers for static content

Static content from a site can put unnecessary load when rendering content. Assets such as images, scripts and styles can be cached using an expire header to stop them from being requested on each HTTP request.

It would be wise to add a version number or date of the change to the end of each static item to allow the cache to be updated when new assets are added. For example

.png?v=1 or .css?v=01012017 .js?v=1

The cache can then be called either through setting a Common HTTP Response Headeror through code

Response.Cache.SetExpires(DateTime.Now.AddYears(1));
Response.Cache.SetCacheability(HttpCacheability.Public);

or by add the following code to your web.config

 <system.webServer>
 <staticContent>
 <clientCache cacheControlCustom="public" cacheControlMaxAge="12:00:00" cacheControlMode="UseMaxAge"/>
 </staticContent>
 </system.webServer>

Umbraco with https on Azure and scheduled published tasks

When forcing a site to run on HTTPS, the following rule is set in the web.config to force a site to 301 redirect to HTTPS when a HTTP link is found

  <rule name="Redirect to https" stopProcessing="true">
 <match url="(.*)" />
 <conditions>
 <add input="{HTTPS}" pattern="off" ignoreCase="true" />
 </conditions>
 <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" appendQueryString="true" />
 </rule>

Whilst initial test will force the site to redirect to HTTPS, not all requests made from umbraco will execute using just this. We also need to ensure that the following key is also set

<add key="umbracoUseSSL" value="true" />

You must also make sure that set the location of the Umbraco endpoint in the umbracoSettings.Config

  <web.routing
 trySkipIisCustomErrors="false"
 internalRedirectPreservesTemplate="false" disableAlternativeTemplates="false" disableFindContentByIdPath="false"
 umbracoApplicationUrl="https://mysite.localhost/umbraco">
 </web.routing>

This will ensure that all requests made from umbraco to /umbraco/RestServices/ScheduledPublish/Index will be sent via HTTPS in the first instance.

When this is not set, a HTTP request is made which will result in the error

A public action method ‘Index’ was not found on controller ‘Umbraco.Web.WebServices.ScheduledPublishController’.

The error indicates that a request has been made via HTTP and redirected to HTTPS which has been rejected.

Once the App Setting has been set, the error will resolve.