Acesso Colaboradores

Como Usar o YARP com Configuração Dinâmica via Banco de Dados no ASP.NET Core

Publicado em por Gustavo Mauricio de Barros

Como Usar o YARP com Configuração Dinâmica via Banco de Dados no ASP.NET Core Como Usar o YARP com Configuração Dinâmica via Banco de Dados no ASP.NET Core

O que é o YARP e por que utilizá-lo?

YARP (Yet Another Reverse Proxy) é um proxy reverso open-source desenvolvido pela Microsoft para o ASP.NET Core.

Com o YARP, é possível construir API gateways, load balancers e proxies reversos escaláveis e eficientes. Eu particularmente gosto muito do YARP, pois ele é extremamente customizável e está bem integrado à pipeline do ASP.NET Core. Em uma arquitetura de microsserviços, um proxy reverso é muito importante para abstrair problemas com autenticação, por exemplo, e atua como uma camada central que unifica o acesso aos seus microsserviços, garantindo segurança e escalabilidade. Dessa forma, seu microsserviço pode se concentrar exclusivamente na lógica de negócio dele.

Na imagem de capa, optei por usar uma foto tirada por mim mesmo no Caminho de Santiago. Acredito que ela representa bem o funcionamento de um proxy direcionando o tráfego aos destinos disponíveis.

Vantagens de carregar a configuração do YARP do banco de dados

Por padrão, o YARP utiliza o arquivo appsettings.json para configurar rotas e clusters, mas essa abordagem possui limitações, como a necessidade de acesso ao servidor para editar a configuração do proxy. Carregar as configurações a partir de um banco de dados traz bastante benefícios, como:

  • Atualizações em tempo real sem downtime;
  • Centralização do gerenciamento de rotas e clusters;
  • Maior escalabilidade e facilidade de manutenção em ambientes distribuídos;
  • Possibilidade de controle e auditoria detalhada das alterações;
  • Interface simplificada para usuários menos técnicos configurarem o proxy.

Como recuperar a configuração do YARP a partir do banco de dados

O YARP não fornece um mecanismo padrão para carregar configurações de um banco de dados, e isso faz sentido, pois está fora do escopo da biblioteca. Portanto, é necessário criar uma interface própria que forneça suas rotas e clusters armazenados. Por exemplo, a interface IReverseProxyRepository:

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

Implementação do IProxyConfigProvider

A interface IProxyConfigProvider do YARP é responsável por fornecer a configuração atual do proxy, incluindo rotas e clusters, para a pipeline do ASP.NET Core. Implementando essa interface, você pode carregar e atualizar as configurações dinamicamente, como no nosso exemplo, diretamente do banco de dados, sem necessidade de reiniciar a aplicação.

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();
    }
}

Implementação do IProxyConfig

A interface IProxyConfig representa a configuração atual do YARP, contendo as coleções de rotas e clusters. Além disso, expõe um ChangeToken que permite ao YARP detectar alterações na configuração, possibilitando atualizações dinâmicas durante a execução.

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();
    }
}

Registro dos serviços no Program.cs

Para finalizar, registre seus serviços em sua Program.cs. Particularmente não sou fã de registrar eles como no exemplo abaixo que criei para fins educativos. Prefiro registrar meus serviços em métodos de extensão como neste exemplo.

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();

Conclusão

Utilizando o IProxyConfigProvider, você garante que o YARP carregue a configuração diretamente do banco de dados ou do lugar que achar mais conveniente para seu projeto, permitindo atualizações dinâmicas e maior controle sobre seu proxy reverso.

Lembre-se que, dependendo do seu sistema e equipe, às vezes manter a configuração no appsettings.json pode acabar sendo mais prático, ainda mais se a configuração do seu proxy nunca for mudar. Gosto muito da frase "Premature optimization is the root of all evil", comece sempre do mais simples e melhore apenas quando existir a necessidade. As vezes seu time não precisa da configuração do banco de dados e você acabou criando uma camada extra de complexidade sem necessidade.

Documentação oficial do YARP

Para mais detalhes técnicos e exemplos, acesse a documentação oficial:

YARP Configuration Providers - Microsoft Docs

← Voltar ao ínicio