Redis Cache – Health Check route in ASP.NET Core

Redis Cache Health Check route in ASPNET Core

In this article, we shall check how to implement the Redis cache Health Check route in ASP.NET Core API or MVC applications.

We will cover below aspects in this article,

There are multiple benefits of using HealthCheck routes in the application,

  • Implementing a health check is mandatory in many stages of the application development life cycle.

  • It helps you to In several stages of the application development life cycle, a health check is required.

  • It allows you to keep real-time track of the health of a variety of resources, databases, and services that your business application relies on.

  • This allows you to swiftly troubleshoot and address database-related technical and environmental issues.

Health check services and middleware in .NET core allow us to validate APIs by allowing us to create health check routes.

It also allows us to validate the health of other resources such as external service connections, external databases, and so on.

Redis Cache Health Check – Getting started

If you already have an API, then please follow below two steps,

Step1 – Implement the Redis IHealthCheck interface

Here please implement the IHealthCheck interface and override the CheckHealthAsync method.

Here we are defining Redis health check using a regular Redis connection.

We shall use the “ConnectionMultiplexer ” to check the connectivity with the Cache and later execute a simple query or command to validate the success or failure of the query.

Let’s now define the CheckHealthAsync which is the IHealthCheck interface method implemented for MongoDB connection.

Below is the implementation of the method,

Above we are injecting the IConnectionMultiplexer interface which we have enabled in the API pipeline within the ConfigureServices method. Please see this article for more details.

HealthCheckResult lets you return health as HealthyDegraded, or Unhealthy statuses.

CheckHealthAsync method is defined as below,

 
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
        {
            try
            {
                foreach (var endPoint in _redisCache.GetEndPoints(configuredOnly: true))
                {
                    var server = _redisCache.GetServer(endPoint);
                    if (server.ServerType != ServerType.Cluster)
                    {
                        await _redisCache.GetDatabase().PingAsync();
                        await server.PingAsync();
                    }
                    else
                    {
                        var clusterInfo = await server.ExecuteAsync("CLUSTER", "INFO");
                        if (clusterInfo is object && !clusterInfo.IsNull)
                        {
                            if (!clusterInfo.ToString()!.Contains("cluster_state:ok"))
                            {
                                return new HealthCheckResult(context.Registration.FailureStatus, description: $"CLUSTER is not is healthy for endpoint {endPoint}");
                            }
                        }
                        else
                        {
                            return new HealthCheckResult(context.Registration.FailureStatus, description: $"CLUSTER unhealthy for endpoint {endPoint}");
                        }
                    }
                }
                return HealthCheckResult.Healthy();
            }
            catch (Exception ex)
            {
                return new HealthCheckResult(context.Registration.FailureStatus, exception: ex);
            }
        }

Step2 – Register Redis Cache health check services

In Startup.ConfigureServices please add the HealthChecks as below, (Please ignore other services as they are more specific to my implementaiton)

    
public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddScoped<ISalaryRepository, SalaryRepository>();
            services.AddDbContext<EmployeeContext>(options =>
            {
                options.UseSqlServer(Configuration.GetConnectionString("EmployeeDB"),
                sqlServerOptionsAction: sqlOptions =>
                {
                    sqlOptions.EnableRetryOnFailure();
                });
            });
            if (_hostEnvironment.IsDevelopment())
            {
                services.AddDistributedMemoryCache();//Use this for only DEV testing purpose
            }
            else
            {
                 services.AddSingleton<IConnectionMultiplexer>(sp => 
                 ConnectionMultiplexer.Connect(new ConfigurationOptions
                {
                  EndPoints = { $"{Configuration.GetValue<string>("RedisCache:Host")}: 
                  {Configuration.GetValue<int>("RedisCache:Port")}" },
                  AbortOnConnectFail = false,
               }));
            }
            services.AddHealthChecks().AddCheck<RedisHealthCheck>("RedisConnectionCheck");
}

Step3 – Enable health check for Redis Middleware in API pipeline

Below is a sample Configure method that enables health checks for Redis Middleware in the API pipeline.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseHttpsRedirection();
            app.UseHealthChecks("/healthcheck");
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

Redis Cache Healthy Status

Let’s start the server and perform the health check,

Once we hit the route /healthcheck we can Healthy status message as below,

blank

Redis Cache Un-Healthy Status

Let’s now stop the server and perform the health check,

blank

Let’s hit the route /healthcheck we will get UnHealthy status message as below,

blank

References:

Do you have any comments or ideas or any better suggestions to share?

Please sound off your comments below.

Happy Coding !!



Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.



Leave a Reply

Your email address will not be published. Required fields are marked *