Softwareentwicklung Zürich & Deutschschweiz

HOW TO USE DISTRIBUTED REDIS CACHE BEHIND A LOAD BALANCER IN DOTNET CORE

29.04.2021
In production we’re often using a load balanced environment (web farm). Since web applications are stateless, most applications need some kind of distributed cache to reduce the load and the amount of requests to fetch data.
In the following blog post I want to show you how to use a redis cache in dotnet core applications. I don’t only want to show you the basics (since these can be found in the Microsoft docs) but I want to go one step further to show you how to handle caching in a web farm.

What is redis?

Redis is an in-memory data structure store. Data is saved as key-value pairs. In comparison to a database, redis is much more performant.

Our Scenario

Dotnet core is the latest open-source and platform independent technology of Microsoft. It’s the successor of the .NET Framework. While working in a .NET environment it was obvious to develop new web applications using dotnet core.
Due to the fact that dotnet core is also running on Mac and Linux systems, some features known from the .NET Framework are now working differently. So dotnet core is not able to handle sticky sessions anymore. This means in a load balanced environment you’ll need to configure a distributed session cache.
In a project at one of my customers we had some requirements to keep mapping data during page reloads. That's why we started saving some data in the session. In our single-server environment this worked perfectly until switching to a web farm.
This means we now have a load balancer which forwards users to one of the different application servers behind. Due to the fact that dotnet core don’t support sticky sessions, anymore, it was clear that we needed a distributed session cache.
Unfortunately, there was no complete documentation available, so in the following, I want to show you how to configure it correctly.

Configuring Redis

For configuring redis cache I would recommend that on this server only redis is running since we expect many calls to the redis cache.

Configuring your dotnet core application

Configuring a distributed redis cache in dotnet core is pretty easy.
You just need to add the Microsoft.Extensions.Caching.Redis nuget package to your application and configure it as follows (in Startup.cs):
public void ConfigureStagingServices(IServiceCollection services)
{
    services.AddDistributedRedisCache(options =>
    {
        options.Configuration = "<REDIS URI>";
        options.InstanceName = "SampleInstance";
    });
}
You will then be able to use the IDistributedCache interface to save data in the redis cache see documentation of Microsoft.
When you’ll need to access the session you will need some more configuration in Startup.cs
services.AddSession(options =>
{
    options.CookieName = "My.Session.Cookie";
});

app.UseSession();
app.UseMvc()
This allows you to access the Session directly
public IActionResult Load()
{
    ViewData["SessionData"] = HttpContext.Session.GetString("MySessionKey");
    return View();
}

public IActionResult Save()
{
    HttpContext.Session.SetString("MySessionKey", "Hello World");
    return View();
}
           
This will work at least when using a single server. This server reads the session cookie which contains a key and uses this key to write and read to/from the redis cache.
When being balanced between different servers this won’t work. Usually, a cookie should be secured so the application has a encryption and decryption key. Unfortunately, this key is not available in the other application servers’ key ring, so they are not able to decrypt the session cookie.
The solution to this is using a dotnet core DataProtection (docs).
I recommend using either an application name or a distributed redis key.
Application name :
services.AddDataProtection().SetApplicationName("My Application Name");
Data protection key and redis url:
var redis = ConnectionMultiplexer.Connect("<REDIS URI>");

services.AddDataProtection().PersistKeysToRedis(redis, "DataProtection-Keys");
Finally, you’ll have a fully working distributed session cache for use in a load-balanced environment
If you have any questions or improvements please send me an email to
© 2016-2021 OneCodex GmbH – All rights reserved