Access Employees

Using YARP with Dynamic Database Configuration in ASP.NET Core

Published in by Gustavo Mauricio de Barros

Using YARP with Dynamic Database Configuration in ASP.NET Core Using YARP with Dynamic Database Configuration in ASP.NET Core

What is YARP and Why Use It?

YARP (Yet Another Reverse Proxy) is an open-source reverse proxy developed by Microsoft for ASP.NET Core.

With YARP, you can build scalable and efficient API gateways, load balancers, and reverse proxies. I personally like YARP a lot because it’s extremely customizable and well integrated into the ASP.NET Core pipeline. In a microservices architecture, a reverse proxy plays a crucial role in abstracting issues like authentication and acts as a central layer that unifies access to your microservices, ensuring security and scalability. This allows each microservice to focus solely on its business logic.

The cover photo is one I personally took on the Camino de Santiago. I believe it nicely illustrates how a proxy directs traffic to the appropriate destinations.

Advantages of Loading YARP Configuration from the Database

By default, YARP uses the appsettings.json file to configure routes and clusters. However, this approach has limitations, such as requiring server access to edit proxy settings. Loading configuration from a database offers several benefits:

  • Real-time updates with no downtime;
  • Centralized management of routes and clusters;
  • Better scalability and maintainability in distributed environments;
  • Detailed control and auditing of changes;
  • Simplified interface for less technical users to configure the proxy.

How to Load YARP Configuration from the Database

YARP doesn't provide a built-in mechanism to load configuration from a database, which makes sense since it's outside the library’s scope. Therefore, you need to implement a custom interface to provide your stored routes and clusters. For example, the interface IReverseProxyRepository:


public interface IReverseProxyRepository
{
    IReadOnlyList<RouteConfig> GetRoutes();
    IReadOnlyList<ClusterConfig> GetClusters();
}

Implementation of IProxyConfigProvider

The IProxyConfigProvider interface in YARP is responsible for supplying the current proxy configuration, including routes and clusters, to the ASP.NET Core pipeline. By implementing this interface, you can load and update configurations dynamically, such as from a database, without restarting the application.


public class DatabaseProxyConfigProvider : IProxyConfigProvider
{
    private volatile IProxyConfig _config;
    private readonly IReverseProxyRepository _repository;

    public DatabaseProxyConfigProvider(IReverseProxyRepository repository)
    {
        _repository = repository;
        _config = LoadConfig();
    }

    public IProxyConfig GetConfig() => _config;

    private IProxyConfig LoadConfig()
    {
        var routes = _repository.GetRoutes();
        var clusters = _repository.GetClusters();
        return new DatabaseProxyConfig(routes, clusters);
    }

    public void Reload()
    {
        _config = LoadConfig();
        _config.SignalChange();
    }
}

Implementation of IProxyConfig

The IProxyConfig interface represents the current configuration for YARP, containing route and cluster collections. It also exposes a ChangeToken to allow YARP to detect configuration changes and dynamically update during runtime.


public class DatabaseProxyConfig : IProxyConfig
{
    private CancellationTokenSource _cts = new CancellationTokenSource();

    public DatabaseProxyConfig(IReadOnlyList<RouteConfig> routes, IReadOnlyList<ClusterConfig> clusters)
    {
        Routes = routes;
        Clusters = clusters;
        ChangeToken = new CancellationChangeToken(_cts.Token);
    }

    public IReadOnlyList<RouteConfig> Routes { get; }

    public IReadOnlyList<ClusterConfig> Clusters { get; }

    public IChangeToken ChangeToken { get; private set; }

    public void SignalChange()
    {
        var previousCts = Interlocked.Exchange(ref _cts, new CancellationTokenSource());
        ChangeToken = new CancellationChangeToken(_cts.Token);
        previousCts.Cancel();
    }
}

Service Registration in Program.cs

Finally, register your services in Program.cs. Personally, I prefer using extension methods to group service registrations, rather than the approach shown below, which is just for educational purposes. For more details, see this Microsoft example.


var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton<IReverseProxyRepository, ReverseProxyRepository>();
builder.Services.AddSingleton<IProxyConfigProvider, DatabaseProxyConfigProvider>();
builder.Services.AddReverseProxy();

var app = builder.Build();

app.MapReverseProxy();

app.Run();

Conclusion

By using IProxyConfigProvider, YARP can load configuration directly from a database or any other preferred source, enabling dynamic updates and greater control over your reverse proxy.

Keep in mind that depending on your system and team, using appsettings.json might be more practical, especially if your proxy configuration is static. I like the phrase "Premature optimization is the root of all evil." Always start simple and only add complexity when it's truly necessary. Sometimes a database configuration layer may just be unnecessary overhead.

Official YARP Documentation

For more technical details and examples, visit the official documentation:

YARP Configuration Providers - Microsoft Docs

← Return to start