In order to improve the page loading speed of my blog for US users, I deployed an App Service in West US region on Azure some time ago. Now I have 2 servers running my blog, East Asia and West US. In this post, I'm going to illustrate how to use Azure to load balancing these servers, so that users can get access to the closest server for their regions.

Adding Identifier Tags


Since the codes deployed in the US and Hong Kong are same, so the web page looks exactly the same, it is impossible to tell which server we are currently accessing from the browser. Thus, I added an environment tag feature to the blog, which is used to tag the server for region information when deploying the code, so that we can easily identify the server we are using.

public static IEnumerable<string> GetEnvironmentTags()
{
    var tagsEnv = Environment.GetEnvironmentVariable("MOONGLADE_TAGS");
    if (string.IsNullOrWhiteSpace(tagsEnv))
    {
        yield return string.Empty;
        yield break;
    }

    var tagRegex = new Regex(@"^[a-zA-Z0-9-#@$()\[\]/]+$");
    var tags = tagsEnv.Split(',');
    foreach (string tag in tags)
    {
        var t = tag.Trim();
        if (tagRegex.IsMatch(t))
        {
            yield return t;
        }
    }
}
endpoints.MapGet("/ping", async context =>
{
    context.Response.Headers.Add("X-Moonglade-Version", Utils.AppVersion);
    var obj = new
    {
        MoongladeVersion = Utils.AppVersion,
        DotNetVersion = Environment.Version.ToString(),
        EnvironmentTags = Utils.GetEnvironmentTags()
    };

    var json = System.Text.Json.JsonSerializer.Serialize(obj);
    await context.Response.WriteAsync(json, Encoding.UTF8);
});

Then I can assign tags for both East Asia and West US deployment in Azure DevOps.

Finally, I can use /ping endpoint to identify current server.

Configure Azure Front Door


I've wrote about Azure Front Door in my previous posts. So this post would not talk about how to create Azure Front Door. For my existing AFD, I need to add the US server to the backend pool.

In Front Door designer, click the existing backend pool, which is "blog-appservice" in my case. 

Add the West US App Service to the list.

Note that Health Probes must be turned on at this time, otherwise Front Door cannot obtain information such as whether the server is available, network delay, etc., and cannot perform load balancing. I use /ping in my case.

My blog site is stateful. For example, when users submit comments, they need to do CSRF verification. When load balancing is configured, it is possible that the first request of the user goes to server A, and the second request goes to server B, so It will cause the second request to be illegal and the blog function will not work properly. 

The solution to this problem is to configure Session Affinity, Front Door will generate a cookie to identify the user, so that the user's subsequent requests are directed to the same server.

In Front Door designer, click the domain name that we need to configure.

Scroll to the bottom of the property page and turn on Session Affinity

Two cookies ASLBSA and ASLBSACORS will appear when visiting the website, which proves that the configuration is successful.

Configure App Service


After actual testing, only turning on Session Affinity on the Front Door still occasionally break the web app state, we also need to turn on ARR affinity on App Service.

ARR affinity uses the Application Request Routing module of IIS, it will also insert a Cookie to identify users. The subsequent requests of this user will not be switched to other servers.

Turn on ARR affinity for both East Asia and West US App Service instances.

Now visit the website, you should see two cookies ARRAffinity and ARRAffinitySameSite, which proves that the configuration is successful.

Verify Load Balancing


Now, when visiting my blog in China, Azure Front Door will direct the traffic to the East Asia server.

When accessing the same domain name in the United States, Azure Front Door will choose the West US server closest to the user.