A 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):
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:
docker run --name testeapi01 -e "MensagemVariavel=destination1" -p 1234:80 -d renatogroffe/apicontagem-dotnet5-preview5:1.0docker run --name testeapi02 -e "MensagemVariavel=destination2" -p 4567:80 -d 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:
dotnet new web -n ExemploYARPLoadBalancer
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 PowerOfTwoChoices, LeastRequests, Random 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 Storage, Azure 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: