No âmbito de aplicações, quando estamos falando de serviços, o desenvolvedor imagina uma API RESTful. Não dá para negar que o casamento de HTTP+JSON faz um grande sucesso, mas em alguns momentos esta combinação possui limitações.
Em larga escala, ou quando se lida com aplicações críticas, a performance de uma API REST pode significar seu gargalo, principalmente quando estamos lidando com microserviços. É por causa disso que grandes empresas, como Netflix, Digital Ocean, SoundClound e Google, optaram pelo gRPC para melhorar e otimizar a comunicação dos seus microserviços.
O gRPC é um framework RPC open source criado pelo Google, como forma de melhorar a comunicação do grande número de microserviços que possuem. Com suporte à várias linguagens, na versão 3.0 do .NET Core 3.0, a Microsoft adicionou um template que facilita a criação de serviços gRPC.
Antes de conhecer este template e criar um serviço, você precisa conhecer mais sobre o gRPC.
Curso C# (C Sharp) - APIs REST com ASP.NET Web API
Conhecer o cursoO que seria o gRPC?
Como dito, o gRPC é um framework RPC. O RPC é a sigla de Remote Procedure Call, chamada de procedimento remoto, que basicamente trata-se de uma tecnologia para comunicação de processos. Permitindo que um computador possa invocar um procedimento de outro computador, independente da linguagem ou plataforma.
No manifesto de motivação e princípios do gRPC o Google conta que já utilizava uma infraestrutura RPC denominada Stubby. Mas por ser muito associada a infraestrutura da empresa e não ser baseado em nenhum padrão, ela não poderia ser aberta a todos. Com o advento do HTTP/2, o Stubby foi refeito e nasceu o gRPC, que hoje é parte da CNCF, Cloud Native Computer Foundation.
Porque o HTTP/2 é importante?
O gRPC não trabalha sob o protocolo HTTP 1.1, que é o protocolo utilizado por todos os servidores web, devido suas limitações. A principal é a forma que as solicitações são tratadas.
Por mais que não seja aparente, no HTTP 1.1 um servidor só pode receber e responder uma requisição por vez. Para tentar contornar este limite, ele trabalha com paralelismo, mas o canal de comunicação trabalha em apenas uma via. Quando está recebendo não pode enviar e vice-versa.
Já no HTTP/2 as conexões são “multiplexadas” (multiplex), o que significa que trabalha de forma bidirecional, recebendo e enviando várias solicitações ao mesmo tempo.
As duas imagens abaixo ilustram este cenário:
Aqui é importante ressaltar que devido ao uso do HTTP/2, um serviço do gRPC só pode ser hospedado em um servidor que fornece suporte a esta versão do protocolo. Felizmente na versão 3.0 do .NET Core, o Kestrel passou a suportar esta versão.
Para conhecer as características deste tipo de serviço, vamos colocar a mão na massa.
Criando um serviço gRPC no ASP.NET Core
A partir da versão 3.0 do .NET core é possível criar um serviço gRPC através do comando abaixo:
dotnet new grpc -o ServicoGrpc
Ou no Visual Studio 2019, selecione o template gRPC Service.
A aplicação criada terá a estrutura abaixo:
Vamos ver em detalhes seus arquivos.
Contrato com Protobuf
Dentro da pasta Protos temos o arquivo greet.proto:
syntax = "proto3";
option csharp_namespace = "ServicoGrpc";
package Greet;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply);
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings.
message HelloReply {
string message = 1;
}
Este é o arquivo de contrato. Baseado no padrão Protobuf, ele que definirá a estrutura do serviço gRPC e precisa existir no cliente e no servidor. É a partir dele que o gRPC irá gerar as operações do serviço.
Acima é definido dentro do pacote Greet
um serviço Greeter
, que contém uma operação, SayHello
. Em seguida é definida a estrutura dos dados recebidos na solicitação e os dados retornados.
Nos bastidores, a biblioteca do gRPC, Grpc.AspNetCore
, irá criar classes, que nos permitirá definir o serviço no C#.
Serviços
Os serviços são definidos dentro da pasta Services, que no momento possui apenas a classe GreeterService
:
public class GreeterService : Greeter.GreeterBase
{
private readonly ILogger<GreeterService> _logger;
public GreeterService(ILogger<GreeterService> logger)
{
_logger = logger;
}
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}
}
Esta classe herda Greeter.GreeterBase
, que foi gerada pelo gRPC com base no arquivo .proto. O mesmo ocorreu com as classes HelloRequest
e HelloReply
.
Servidor
Por fim, no arquivo appsettings.json é definido que o Kestrel utilizará o protocolo HTTP/2:
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http2"
}
}
E na classe Startup
, além de registrar o serviço gRPC, cria-se um fallback para caso de o usuário acessar o serviço pelo navegador ou utilizando um client sem suporte ao gRPC:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>();
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
});
});
}
}
Cliente
Para acessar um serviço gRPC necessitamos de um cliente com suporte a este tipo de serviço, para isso, irei utilizar uma aplicação console simples:
class Program
{
static async Task Main(string[] args)
{
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "Treinaweb Blog" });
Console.WriteLine("Saudacao: " + reply.Message);
Console.WriteLine("Pressione qualquer coisa para sair...");
Console.ReadKey();
}
}
Que precisa referenciar as bibliotecas Google.Protobuf
, Grpc.Net.Client
e Grpc.Tools
:
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.11.1" />
<PackageReference Include="Grpc.Net.Client" Version="2.25.0" />
<PackageReference Include="Grpc.Tools" Version="2.25.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
Além claro do arquivo greet.proto definido do servidor:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
No servidor, o atributo GrpcServices
é definido com o valor Server
.
Ao executar ambas as aplicações, inicialmente o serviço e por fim o cliente, poderemos ver a comunicação sendo realizada:
Curso C# (C Sharp) - Introdução ao ASP.NET Core
Conhecer o cursoConclusão
No momento há poucos servidores web com suporte ao gRPC, mas esta tecnologia possui muito potencial. Em uma arquitetura de microserviços é altamente recomendado que ela seja utilizada para a comunicação entre os microserviços. Neste ambiente a comunicação externa pode se manter com a tradicional combinação HTTP+JSON.
Até a próxima.