Published on
🍵 2 min read

Implementing Redis Pub/Sub with .NET Aspire: A Simple Guide

Authors

Photo

Overview

    What is Redis Pub/Sub?

    Redis Pub/Sub (Publish/Subscribe) is a messaging pattern where:

    • Publishers send messages to channels
    • Subscribers listen to specific channels
    • Publishers and subscribers are decoupled
    • Messages are delivered in real-time

    First, let's look at the AppHost configuration:

    App Host:

    var builder = DistributedApplication.CreateBuilder(args);
    var redis = builder.AddRedis("redis");
    builder.AddProject<Projects.Api>("api")
        .WithReference(redis)
        .WithReplicas(1);
    builder.AddProject<Projects.Worker>("worker")
        .WithReference(redis);
    await builder.Build().RunAsync();
    

    In this configuration, we set up Redis. You need to install the Aspire.Hosting.Redis package.

    The application consists of an API service for publishing messages and a background worker for reading them. The API service sends the message to Redis channel:

    Api/Program.cs

    // ... (initialization code)
    builder.AddRedisDistributedCache("redis");
    

    As you can see, we need to add Redis to the API service first. For this, you need to install the Aspire.StackExchange.Redis.DistributedCaching package.

    app.MapPost("/send-message", async ([FromBody] SendMessageRequest request, IConnectionMultiplexer connectionMultiplexer) =>
    {
        await connectionMultiplexer.GetSubscriber().PublishAsync(Constants.DefaultChannel, request.Message);
        return Results.Ok();
    });
    

    The background worker then gets the messages from Redis channel and writes a log message:

    using RedisPubSub.ServiceDefaults;
    using StackExchange.Redis;
    
    namespace Worker;
    
    public class Worker(ILogger<Worker> logger, IConnectionMultiplexer connectionMultiplexer) : BackgroundService
    {
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                await connectionMultiplexer.GetSubscriber().SubscribeAsync(Constants.DefaultChannel, (channel, message) =>
                {
                    logger.LogWarning("Here is the message: {Message} from channel: {ChannelName}", message, Constants.DefaultChannel);
                });
                await Task.Delay(5000, stoppingToken);
            }
        }
    }
    

    Here are screenshots from testing:

    api-send
    api-telemetry
    worker-telemetry
    worker-log

    Conclusion

    With .NET Aspire, implementing Redis Pub/Sub becomes straightforward. This pattern is excellent for building scalable, real-time applications with decoupled components. As you explore further, you'll find even more ways to leverage Redis and .NET Aspire in your cloud-native applications.

    For the complete source code of this example, you can visit: aspire-samples