.NET

19 nov, 2020

Novidades do .NET 5: implementando um proxy reverso com YARP + ASP.NET 5

Publicidade
Image for post

Microsoft disponibilizou durante o Build 2020 o Preview 1 do projeto YARP, uma solução para a implementação de aplicações que funcionem como proxy reverso e que emprega a infraestrutura do ASP.NET (possuindo compatibilidade com .NET Core 3.1 e .NET 5):

A construção desta alternativa segue em andamento, contando inclusive com um repositório público no GitHub em que é possível acompanhar/discutir sua evolução:

https://github.com/microsoft/reverse-proxy

Neste novo artigo de novidades do .NET 5/ASP.NET 5 trarei um exemplo de implementação de um proxy reverso/load balancer baseado no projeto YARP. Para os testes aqui descritos instalei o Preview 5 do .NET 5 (lançado recentemente), com informações adicionais sobre este release podendo ser encontradas no post:

Nos testes envolvendo load balancing criei 2 containers Docker, fazendo uso para isto da imagem pública renatogroffe/apicontagem-dotnet5-preview5:1.0:

Disponibilizei no GitHub o projeto que utilizei na geração desta imagem; trata-se de uma API REST baseada no ASP.NET 5 e criada a partir do Preview 5 do .NET 5:

ASP.NET 5 Preview 5 + REST API + Docker + Linux Alpine

O próximo passo será criar uma aplicação baseada no template ASP.NET Core Empty:

Adicionei neste projeto a versão 1.0.0-preview.1.20268.2 do package Microsoft.ReverseProxy:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.ReverseProxy" Version="1.0.0-preview.1.20268.2" />
  </ItemGroup>

</Project>

As configurações para que esta aplicação funcione como load balancer/proxy reverso foram definidas no item ReverseProxy do arquivo appsettings.json:

  • Em Routes temos as configurações de redirecionamento. Uma única rota (appcontagem) foi declarada neste elemento, o que inclui o caminho de redirecionamento (Path), os mapeamentos a serem resolvidos via load balancer (backendContagem) e as operações possíveis para a mesma (neste exemplo apenas GET);
  • Já em Backends estão as configurações para backendContagem. No item Mode de LoadBalancing foi especificado o valor RoundRobin (outras opções/algoritmos de balanceamento de carga são PowerOfTwoChoicesLeastRequestsRandom e First). Os endereços para redirecionamento estão declarados em Destinations (backendContagem_destination1 e backendContagem_destination2).
{
  "ReverseProxy": {
    "Routes": [
      {
        "RouteId": "appcontagem",
        "BackendId": "backendContagem",
        "Match": {
          "Methods": [ "GET" ],
          "Host": "localhost",
          "Path": "/{**catchall}"
        }
      }
    ],
    "Backends": {
      "backendContagem": {
        "LoadBalancing": {
          "Mode": "RoundRobin"
        },
        "Destinations": {
          "backendContagem_destination1": {
            "Address": "http://localhost:1234/"
          },
          "backendContagem_destination2": {
            "Address": "http://localhost:4567/"
          }
        }
      }
    }
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Por fim, ajustes serão realizados também na classe Startup:

  • Em ConfigureServices será acionado o método AddReverseProxy, com o mesmo recebendo as configurações que se encontram na seção ReverseProxy do arquivo appsettings.json;
  • Na chamada a UseEndpoints no método Configure foi acionada a operação MapReverseProxy. Ao invocar o método UseProxyLoadBalancing a partir do objeto proxyPipeline será ativado o mecanismo de load balancing/proxy reverso.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace ExemploYARPLoadBalancer
{
    public class Startup
    {
        public IConfiguration Configuration { get; }
        
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddReverseProxy() 
                .LoadFromConfig(Configuration.GetSection("ReverseProxy"));
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapReverseProxy(proxyPipeline =>
                {
                    proxyPipeline.UseProxyLoadBalancing();
                });
            });
        }
    }
}

Nas imagens a seguir temos 2 testes de acesso. Ao efetuar requisições para o endereço https://localhost:5001/contador (a aplicação que funciona como proxy reverso está executando na porta 5001) tivemos como retorno respostas produzidas pelas 2 instâncias da API de contagem:

Executando o script PowerShell indicado na próxima listagem:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

For ($i = 0; $i -lt 6; $i++) {
    $resultado = Invoke-WebRequest -Uri "https://localhost:5001/contador" -Method GET
    $resultado.Content
}

Teremos o resultado do processamento de 6 requisições em sequência, com as respostas geradas alternadamente por cada uma das 2 instâncias da API de contagem:

O código-fonte deste projeto para testes com YARP também foi disponibilizado no GitHub:

https://github.com/renatogroffe/ASPNET5-Preview5_YARP-LoadBalancer

O exemplo de load balancing/proxy reverso detalhado neste artigo é uma variação de outra demonstração que realizei em um artigo sobre NGINX:

ASP.NET Core: implementando Load Balancing com Nginx, Docker e Docker Compose

E para concluir este post deixo aqui um convite…

Caso você precise conhecer mais sobre o Microsoft Azure como um todo, não deixe de aproveitar o preço promocional (apenas R$ 255,00) da segunda turma online do treinamento Azure na Prática com foco em Desenvolvimento Web que acontecerá dia 20/06/2020 (um sábado).

Aproveite para aprender mais sobre as possibilidades oferecidas por serviços do Microsoft Azure como App Service (para hospedagem de Web Apps, com suporte a ASP.NET Core e Docker), Azure StorageAzure Functions + Logic Apps (soluções serverless), Azure App Configuration + Key Vault… E o melhor, no conforto de sua casa! Acesse o link a seguir para informações e efetuar sua inscrição:

https://bit.ly/anp-web3-blog-groffe