Scale your application globally with Azure Series - Part 2 - Azure CDN
Tags: csharp, azure, azurefunctions
Published: 2019-10-24 10:14:31

---
title: Scale your application globally with Azure Series - Part 2 - Azure CDN
published: true
description: This is part two of a three-part series that shows you how to use Azure to distribute your application globally and ensure that users get the best experience.  In this part,  we look at using Azure CDN to distribute static content.
tags: csharp,
  azure,
  azure_functions
cover_image: https://blogs.siliconorchid.com/images/coding-inspiration/global-scaling/global-network-devto-version.jpg
series: Scale your application globally with Azure
canonical_url: https://blogs.siliconorchid.com/post/coding-inspiration/global-scaling/part2-cdn/
---

This article was originally published at [blogs.siliconorchid.com](https://blogs.siliconorchid.com/post/coding-inspiration/global-scaling/part2-cdn/) on 29-May-2019


**This is part two of a three-part series that shows you how to use Azure to distribute your application globally and ensure that users get the best experience.**

> In [part 1 of this series](https://blogs.siliconorchid.com/post/coding-inspiration/global-scaling/part1-introduction/), we talk about how to scale an application and look at a demonstration application.

> In [part 2 of this series](https://blogs.siliconorchid.com/post/coding-inspiration/global-scaling/part2-cdn/), we look at using *Azure CDN* to distribute static content.

> In [part 3 of this series](https://blogs.siliconorchid.com/post/coding-inspiration/global-scaling/part3-frontdoor/), we look at using *Azure Front Door* to globally distribute an application back end hosted in dual Azure Regions.

<br/>

<hr/>


## Use Azure Content Delivery Network (CDN) for static content

If your application has only static content, such as a blogsite like mine, or a JavaScript application that only consumes APIs from third-parties, then using a CDN is a perfect way to distribute your files.

### What is a CDN?

A CDN is a globally distributed network of servers.  Data is replicated in a large number of different geographic locations, so as to bring copies physically nearer to users around the planet.  

* Each location of the network is called a "node" (or "edge server").  

* CDNs work by seeding from a single source of data and replicating copies out to the various nodes on the network.  

* Something to be aware of is that when you update a file at the source,  you cannot expect the content to update across the network instantly - it can sometimes take a few minutes to propagate globally. 

* Often, a single country may have multiple nodes, located in different cities, to further increase the chance of geographic proximity to a user.   

* When requesting a piece of data, the network determines which node will be fastest for the user and serves from that node accordingly.


Even if you've never set up your own CDN, there's a very good chance that you are already familiar with consuming content from one, because it's very common to put a reference to an open-source JavaScript library/resource (e.g. Bootstrap)  as a link on a webpage.   There are several benefits to doing so:-

* Files can be requested and downloaded more quickly (because of physical proximity). 
* If you are referencing a popular shared resource (e.g. many sites reference the same copy of bootstrap from a Google CDN), there is a good chance that your user may already have a locally cached copy of the resource.  
* It may save bandwidth charges if another organisation is responsible for hosting shared content.

<br/>
<hr/>

![image showing a lady being hit by a barrage of paper files](https://blogs.siliconorchid.com/images/coding-inspiration/global-scaling/file-barrage.gif#shadow)


### How does a CDN apply to you?

For many developers, the de facto place to publish their **entire** website content will be the tried and trusted web server (or perhaps a derivative, such as an [*Azure WebApp Service*](https://azure.microsoft.com/en-gb/services/app-service/web/)).  

Such a website will likely be used to serve up both active content, e.g. MVC pages and RESTful APIs, and static content such as stylesheets, images, SPA payloads, etc.  

The static content can be a barrage of many smaller files, each of which your server needs to process.  This incurs a load on resources such as CPU, memory, network bandwidth, etc.

If this is how you currently work, I would **strongly recommend that you review which parts of your application are purely static content and consider publishing these separately to a CDN**.  Your users could benefit immediately from improved download times and your servers could benefit from a reduced overall traffic load. 

Static content doesn't just represent obvious items such as .css and images, it could also represent the compiled payload of your JavaScript SPA application which even when minified could easily be a large download.



You should note that despite having huge capacity and global reach, CDNs are relatively cheap to provision.  You can read about [*Azure CDN* charges here](https://azure.microsoft.com/en-gb/pricing/details/cdn/).  

The Azure Portal provides an element of choice and convenience, directly offering alternative services from both Akamai and Verizon.



Something that you may find interesting, is the list of physical CDN node locations.  Check out this link for a [list of *Azure CDN* locations](https://docs.microsoft.com/en-us/azure/cdn/cdn-pop-locations). 

> Unrelated to Azure, but definitely worth mentioning, if you are an individual with a personal website e.g. a budding blogger like me, [Cloudflare offers a free pricing tier](https://www.cloudflare.com/en-gb/plans/) which could be perfect for you! 

<br/>
<hr/>

### Create an Azure Resource Group

We've been covering a lot of theory so far, it's about time we made a start on our demonstration project.

Firstly, we need a way to keep our Azure resources grouped together logically, so we need to make a *Resource Group*

* If you don't know how to create a *Resource Group*, refer to this [Microsoft Documentation Guide : Manage Azure Resource Manager resource groups by using the Azure portal]
(https://docs.microsoft.com/en-us/azure/azure-resource-manager/manage-resource-groups-portal)
* In this demo I have created a new group called "GlobalScalingDemo"

<br/>
<hr/>

### Create and configure an Azure Storage Static Website

A CDN requires a source of data to work from.   In our demo, we'll be using an *Azure Storage Static Website* for this purpose.

It's worth clarifying that an *Azure CDN*  **does not need a website as it's source** - for a couple of years now, it has been possible to connect a CDN **directly** to files in a storage container.   

There is an easy-to-overlook reason as to why we specifically want to use the recently new *Azure Storage Static Site* option - this relates to the default webpage (and default "not found" page).      Without a web server, *Azure Storage* simply serves up files - it doesn't understand the concept of a default web page, meaning that `index.html` has no significance.    The only way you could load the homepage would be to explicitly ask for it in the URL i.e. something like `www.mywebsite.com/index.html`.    However, with the *Static Site* feature enabled and configured, we can use a naked URL and correctly serve up the default page as expected i.e. just `www.mywebsite.com`.

> If your application has no requirement to serve a homepage, you can bypass the advice to create a *Static Website* and simply connect the CDN directly to the exposed URL of the storage container (making sure that the container has public visibility turned on!)

* We now need to create an *Azure Storage Static Website*.   If you don't already know how to do this, you should refer to my [previous article](https://blogs.siliconorchid.com/post/coding-inspiration/whatsapp-signalrservice-azurefunction/part3-deploy-to-cloud/#createazurestoragestaticwebsite), which details exactly the steps you need to take. 

* In this demo, I've given my resource the name `globalscalingdemostorage` which exposes an endpoint called `https://globalscalingdemostorage.z6.web.core.windows.net/` - but you will need to provide your own unique name.

* When the new resource has been provisioned, you will need to copy the content for the demo website across to the `$web` container.  There are a couple of ways you could do this, but we [discussed using the *Azure Storage Explorer* in the previous article](https://blogs.siliconorchid.com/post/coding-inspiration/whatsapp-signalrservice-azurefunction/part3-deploy-to-cloud/#uploadfilestoazurestoragestaticwebsite).     

> If you are uncertain what content needs to be copied, it should be everything in the folder `....\GlobalScalingDemo\src\GlobalScalingDemo.Web\wwwroot`

Please note that at this point in time, we have not set up a backend system, so we don't know what the endpoint will be.   As such, we cannot set this value in JavaScript,  so the client app will be expected to error.

<br/>
<hr/>

### Create and configure the Azure CDN
Now that we've created a website as a source, we can now go ahead and create the actual Azure CDN.

* From your resource group, click the **Add** new resource button and search for "CDN"
* From the "Microsoft CDN" blade, click **Create** to start the process. 
* Populate the fields.  For some of these fields, you will need to provide your own unique name.   For the demo I used these settings:
    * **Name**:  "globalscalingdemocdn" - noting that I suffixed this resource name with "cdn" to make it clear what this was.
    * **Resource Group**:  select the resource group that you created earlier.  For me, I used "GlobalScalingDemo".
    * **Resource Group Location**:  This setting is greyed-out and cannot be edited - it inherits from the location associated with the parent resource group.
    * **Pricing Tier**: You have a number of options here, with different providers offering different types of service at different price points.  You can [review a matrix of features here](https://docs.microsoft.com/en-us/azure/cdn/cdn-features).   For the sake of this demo, we're going to choose the default "Standard Microsoft". 
    * We want to be able to define a custom URL Endpoint for our CDN, so go ahead and check the tickbox for "Create a new CDN Endpoint now".     Doing so will reveal further options:-
    * **CDN Endpoint Name** : "globalscalingdemocdnendpoint" - noting that I suffixed this resource name with "cdnendpoint" to make it clear what this was.
    * **Origin** : Now this is important!  You should resist any instinct to select the option called "Storage" and instead choose **"Custom Origin"**.    The difference is that the "storage" option is used to connect the CDN to a regular storage container, whereas when we use a static website, we need to connect our CDN to the endpoint of that static website instead.
    * **Origin Hostname** : You need to use the primary endpoint of the Azure Storage Static Website.    Be careful cutting+pasting the value though, as you need to remove both the leading "https://" and the trailing "/".    For my demo, this means I would enter `globalscalingdemostorage.z6.web.core.windows.net` into the field - but you will have to provide your own unique version.

![image showing azure CDN creation](https://blogs.siliconorchid.com/images/coding-inspiration/global-scaling/create-azure-cdn.png#shadow)

> **Note:**  There is a bit of an "unpolished user experience" in the Azure Portal UI, that you should keep an eye out for, related to the option "Resource Group Location".   

> An example of this manifested whilst researching this article.   I had originally selected "UK South" to be the location of my resource group.   When I came to create the CDN, the option showed "Australia",  which was disabled (greyed out) and prevented me from changing it.   When I tried to create the CDN resource, the portal threw an error and wouldn't let me proceed.   

> Not all Azure Regions (datacentres) are equal, with some providing more services than others.  Although a CDN is inherently a global service, it still needs to be allocated to an Azure region (the resource metadata needs to be associated with something).   

> The problem was that only certain Azure Regions support a CDN, but this isn't necessarily apparent up-front.   

> Evidently, my underlying "UK" selection couldn't be matched to any of those valid regions, in the drop-down list, so "Australia" was being selected as it was alphabetically the first.

> As such, the fix was to create a replacement resource group, selecting a major Azure Region (I happened to use Europe West instead).  

<br/>

<br/>

That's pretty much all you need to do to get a basic working result!

If you navigate to the CDN-Endpoint resource in the portal and view the "overview", it will confirm to you what the Endpoint Hostname is.   If you like, you can open this link in a browser window and view your globally-distributed website right now!
As a reminder, in this example, that CDN-serviced endpoint is as follows: 

`https://globalscalingdemocdnendpoint.azureedge.net`

Yours will look similar to the following:

`https://<your CDN Endpoint Name >.azureedge.net`

<br/>

<hr/>

There are a few other things worth talking about:

* You can, of course, assign your own custom domain to the CDN.   This is beyond the intended scope of this article, but you can follow this [Microsoft Tutorial : Add a custom domain to your Azure CDN endpoint
](https://docs.microsoft.com/en-us/azure/cdn/cdn-map-content-to-custom-domain).    
* **A feature I really, really like about Azure CDN** is that there is an option for "complete certificate management".  
     * This means that HTTPS is handled for you and that Azure automatically provisions an SSL  certificate, for your custom domain,  **for free**.    
     * If, like me, you're more accustomed to having to purchase an SSL certificate, which can be really expensive!)You'll also be used to generating the actual certificate file, uploading it to a provider and remembering to renew it, etc - then you'll be delighted to hear that this expensive chore just goes away.   
     * You can read more about this in the [Tutorial: Configure HTTPS on an Azure CDN custom domain
](https://docs.microsoft.com/en-us/azure/cdn/cdn-custom-ssl?tabs=option-1-default-enable-https-with-a-cdn-managed-certificate)

> The only limitation I have discovered with using a CDN, is that **you cannot assign the CDN to your Apex domain** (i.e. a "naked domain" without any subdomain).   For example, you cannot assign "https://mysite.com" - it has to include a subdomain, such as "www" or "blog" etc.   

>  If you're familiar with this subject, behind the scenes, you will be using [CNAME records](https://www.pickaweb.co.uk/kb/cname-can-use-domain/) (which are domain-name-based) in your DNS control panel and not [A records](https://support.dnsimple.com/articles/a-record/) (which are IP-based).   I had briefly hoped that using a [DNS ALIAS record](https://support.dnsimple.com/articles/alias-record/) (a DNS workaround offered by some [registrars](https://www.cloudflare.com/learning/dns/glossary/what-is-a-domain-name-registrar/)) could have been a solution, but no, it simply isn't supported.  Because of the dynamic nature of the CDN service, this does actually make sense if you think it through!   Just in case I was providing incorrect advice, [I checked with Azure Advocate Jim Bennett](https://twitter.com/jimbobbennett/status/1097551343814955008) who confirmed this for me.  

<br/>
<hr/>

Next, in part three, we'll be looking at how you can use *Azure Front Door* to globally distribute all parts of our application, along with one way how we can scale by using multiple instances hosted in different data centres.  

<a href="https://blogs.siliconorchid.com/post/coding-inspiration/global-scaling/part3-frontdoor/" class="button is-primary">
 <i class="fas fa-file-alt ml-1" style="margin-right:10px;" > </i> NEXT:  Read part 3</a>