Recently I had to investigate a performance issue problem where images from Sitecore through an Azure CDN were being delivered very slowly. Very small images of 7kb in size were taking 500ms – 1.5s and it was causing the website to perform very poorly.
This turned out to be purely more than just a Sitecore issue and this blog article discusses some of the problems and issues which you are likely to come across when dealing with a content delivery network.
Hit or Miss
Content Delivery Networks generally have a concept of hit and miss whereby the hit delivers the content directly to the user and a miss returns to the origin. With an Azure CDN it is possible to identify whether it is a hit or a miss by looking at the response headers.
The response header x-cache: HIT is added to the response header if the CDN has achieved a HIT but if this is missing then it has gone back the origin and there will be no similar MISS identifier header. These are easily visible through the network tools in Chrome
One thing to note about this header is that it is not part of the HTTP Header standards which is why it has the x prefix
When having issues with any CDN vendor one of the best methods to receive support is to provide a HAR file which provides all of the diagnostic data. This can be generated in Chrome by when using the Network tab. Once the traffic has loaded on the page right click and select Save all as HAR with content which will generate a JSON file.
If you want to view this data in a useful format to analyse the problems, then there is a great tool provided at http://www.softwareishard.com/har/viewer/
Content delivery networks depend on having point-of-presence locations in your near vicinity. They also require having a connection with your ISP and if they do not then your ISP will use the next pop location. Each provider varies so it is good to find out from a possible vendor what pop locations they offer.
Each unique query string has its own cache key which is stored within the CDN. This cache key is then replicated through the various geographical locations using by the content delivery network provider. By adding query string keys, you are adding more variation and complexity this is a very common cause of why items respond with a miss. Reducing this complexity will definitely lead to a better hit rate.
Content can obviously change quite frequently on a Sitecore website and updated images will require purging. There are two ways around this:
Most IIS based websites now have Dynamic Compression enabled which will allow the website to server to serve files using gzip compression. Unfortunately, even if this is enabled this won’t be replicated on the CDN and also needs to be configured there. Unfortunately the compression will only work for items which are cacheable so you will notice that pages do show as using gzip compression
This can be achieved in the CDN settings under:
Settings > Compression and it gives you the ability to specify the file types which you actually want to compress.
Image Uncacheable Viewer
Dependent on the provider you can analyse the status of the CDN Cache to a certain degree. Through the Supplemental Management Portal in the Azure Portal you can find out whether images are being cached as expected.
Using a Azure CDN Verizon account this can be located under:
Analytics > Edge Performance Analytics > Http Large Object > CacheStatusUncacheable.
This will list out all of the items which are not cached on your website. The list itself will generally consist of popular pages and items that may not require caching.
The default setting in Sitecore for caching images is set to private but CDN’s require it to be public. Public marks the response as cacheable where as private means that the cache is specific to one user/instance. When using private this will cause traffic to route via the CDN and return to the origin.
Cache-Control: private, max-age=604800
By default the cache-control setting in Sitecore.config is set to private. This can be easily changed in the Sitecore configuration using a simple patch file
<?xml version="1.0" encoding="UTF-8"?>
<sitecore xmlns:p="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/" xmlns:s="http://www.sitecore.net/xmlconfig/set/">
<setting name="MediaResponse.Cacheability" s:value="public" />