gRPC JSON transcodificação no ASP.NET Core

Por James Newton-King

O gRPC é uma estrutura de RPC (Chamada de Procedimento Remoto) de alto desempenho. O gRPC usa HTTP/2, streaming, Protobuf e contratos de mensagens para criar serviços de alto desempenho e em tempo real.

Uma limitação com gRPC é que nem todas as plataformas podem usá-la. Os navegadores não dão suporte total a HTTP/2, tornando as APIs REST e JSON a principal maneira de obter dados em aplicativos do navegador. Apesar dos benefícios que o gRPC traz, as APIs REST e JSON têm um lugar importante em aplicativos modernos. A criação de APIs Web gRPC eJSON adiciona sobrecarga indesejada ao desenvolvimento de aplicativos.

Este documento discute como criar APIs da Web JSON usando serviços gRPC.

Visão geral

A transcodificação JSON de gRPC é uma extensão para ASP.NET Core que cria APIs RESTful JSON completas para serviços gRPC. Depois de configurada, a transcodificação permite que os aplicativos chamem serviços gRPC com conceitos HTTP conhecidos:

  • Verbos HTTP
  • Associação do parâmetro de URL
  • Solicitações/respostas JSON

O gRPC ainda pode ser usado para chamar serviços.

Observação

A transcodificação gRPC JSON substitui a API HTTP gRPC, uma extensão experimental alternativa.

Uso

  1. Adicione uma referência de pacote para Microsoft.AspNetCore.Grpc.JsonTranscoding.

  2. Registre a transcodificação no código de inicialização do servidor adicionando AddJsonTranscoding : No arquivo Program.cs, altere builder.Services.AddGrpc(); para builder.Services.AddGrpc().AddJsonTranscoding();.

  3. Adicione <IncludeHttpRuleProtos>true</IncludeHttpRuleProtos> ao grupo de propriedades no arquivo de projeto (.csproj):

    <Project Sdk="Microsoft.NET.Sdk.Web">
    
      <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
        <InvariantGlobalization>true</InvariantGlobalization>
        <IncludeHttpRuleProtos>true</IncludeHttpRuleProtos>
      </PropertyGroup>
    
  4. Anote os métodos gRPC em seus arquivos .proto com associações HTTP e rotas:

    syntax = "proto3";
    
    option csharp_namespace = "GrpcServiceTranscoding";
    import "google/api/annotations.proto";
    
    package greet;
    
    // The greeting service definition.
    service Greeter {
      rpc SayHello (HelloRequest) returns (HelloReply) {
        option (google.api.http) = {
          get: "/v1/greeter/{name}"
        };
      }
    }
    
    // The request message containing the user's name.
    message HelloRequest {
      string name = 1;
    }
    
    // The response message containing the greetings.
    message HelloReply {
      string message = 1;
    }
    

O método gRPC SayHello agora pode ser invocado como gRPC e como uma API da Web JSON:

  • Solicitação: GET /v1/greeter/world
  • Resposta: { "message": "Hello world" }

Se o servidor estiver configurado para gravar logs para cada solicitação, os logs do servidor mostrarão que um serviço gRPC executa a chamada HTTP. A transcodificação mapeia a solicitação HTTP de entrada para uma mensagem gRPC e converte a mensagem de resposta em JSON.

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET https://localhost:5001/v1/greeter/world
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint 'gRPC - /v1/greeter/{name}'
info: Server.GreeterService[0]
      Sending hello to world
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint 'gRPC - /v1/greeter/{name}'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 1.996ms 200 application/json

Anotar métodos gRPC

Os métodos gRPC devem ser anotados com uma regra HTTP antes de dar suporte à transcodificação. A regra HTTP inclui informações sobre como chamar o método gRPC, como o método HTTP e a rota.

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      get: "/v1/greeter/{name}"
    };
  }
}

O exemplo de continuação:

  • Define um serviço Greeter com um método SayHello. O método tem uma regra HTTP especificada usando o nome google.api.http.
  • O método é acessível com solicitações GET e a rota /v1/greeter/{name}.
  • O campo name na mensagem de solicitação está associado a um parâmetro de rota.

Muitas opções estão disponíveis para personalizar como um método gRPC se associa a uma API RESTful. Para obter mais informações sobre como anotar métodos gRPC e personalizar JSON, consulte Configurar HTTP e JSON para transcodificação gRPC JSON.

Métodos de streaming

O gRPC tradicional por HTTP/2 dá suporte ao streaming em todas as direções. A transcodificação é limitada apenas ao streaming de servidor. Não há suporte para streaming de cliente e métodos de streaming bidirecional.

Os métodos de streaming de servidor usam JSON delimitado por linha. Cada mensagem escrita usando WriteAsync é serializada para JSON e seguida por uma nova linha.

O seguinte método de streaming de servidor grava três mensagens:

public override async Task StreamingFromServer(ExampleRequest request,
    IServerStreamWriter<ExampleResponse> responseStream, ServerCallContext context)
{
    for (var i = 1; i <= 3; i++)
    {
        await responseStream.WriteAsync(new ExampleResponse { Text = $"Message {i}" });
        await Task.Delay(TimeSpan.FromSeconds(1));
    }
}

O cliente recebe três objetos JSON delimitados por linha:

{"Text":"Message 1"}
{"Text":"Message 2"}
{"Text":"Message 3"}

Observe que a configuração WriteIndentedJSON não se aplica aos métodos de streaming de servidor. A reformatação automática adiciona novas linhas e espaço em branco a JSON, que não podem ser usadas com JSON delimitado por linha.

Veja ou baixe uma amostra de aplicativo de transcodificação e streaming gPRC do ASP.NET Core.

Protocolo HTTP

O modelo de serviço gRPC do ASP.NET Core, incluído no SDK do .NET, cria um aplicativo configurado apenas para HTTP/2. O HTTP/2 é um bom padrão quando um aplicativo dá suporte apenas ao gRPC tradicional por HTTP/2. A transcodificação, no entanto, funciona com HTTP/1.1 e HTTP/2. Algumas plataformas, como UWP ou Unity, não podem usar HTTP/2. Para dar suporte a todos os aplicativos cliente, configure o servidor para habilitar HTTP/1.1 e HTTP/2.

Atualize o protocolo padrão em appsettings.json:

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1AndHttp2"
    }
  }
}

Como alternativa, configure pontos de extremidade Kestrel no código de inicialização.

A habilitação de HTTP/1.1 e HTTP/2 na mesma porta requer TLS para negociação de protocolo. Para obter mais informações sobre como configurar protocolos HTTP em um aplicativo gRPC, consulte Negociação de protocolo gRPC do ASP.NET Core.

Transcodificação gRPC JSON vs gRPC-Web

A transcodificação e a gRPC-Web permitem que os serviços gRPC sejam chamados de um navegador. No entanto, a maneira como cada um faz isso é diferente:

  • O gRPC-Web permite que aplicativos de navegador chamem serviços gRPC do navegador com o cliente gRPC-Web e o Protobuf. O gRPC-Web requer que o aplicativo do navegador gere um cliente gRPC e tem a vantagem de enviar mensagens de Protobuf pequenas e rápidas.
  • A transcodificação permite que os aplicativos do navegador chamem serviços gRPC como se fossem APIs RESTful com JSON. O aplicativo do navegador não precisa gerar um cliente gRPC nem saber nada sobre gRPC.

O serviço Greeter anterior pode ser chamado usando APIs JavaScript do navegador:

var name = nameInput.value;

fetch('/v1/greeter/' + name)
  .then((response) => response.json())
  .then((result) => {
    console.log(result.message);
    // Hello world
  });

grpc-gateway

grpc-gateway é outra tecnologia para criar APIs RESTful JSON de serviços gRPC. Ele usa as mesmas anotações .proto para mapear conceitos HTTP para serviços gRPC.

grpc-gateway usa a geração de código para criar um servidor proxy reverso. O proxy reverso converte chamadas RESTful em gRPC+Protobuf e envia as chamadas por HTTP/2 para o serviço gRPC. O benefício dessa abordagem é que o serviço gRPC não sabe sobre as APIs RESTful JSON. Qualquer servidor gRPC pode usar grpc-gateway.

Enquanto isso, a transcodificação gRPC JSON é executada dentro de um aplicativo ASP.NET Core. Ele desserializa JSON em mensagens de Protobuf e invoca o serviço gRPC diretamente. A transcodificação em ASP.NET Core oferece vantagens para os desenvolvedores de aplicativos .NET:

  • Menos complexo: os serviços gRPC e a API RESTful JSON mapeada são executados em um aplicativo ASP.NET Core.
  • Melhor desempenho: a transcodificação desserializa JSON para mensagens de Protobuf e invoca o serviço gRPC diretamente. Há benefícios significativos de desempenho em fazer isso em processo em vez de fazer uma nova chamada gRPC para um servidor diferente.
  • Custo mais baixo: menos servidores resultam em uma conta de hospedagem mensal menor.

Para instalação e uso do grpc-gateway, consulte o LEIAME grpc-gateway.

Recursos adicionais

O gRPC é uma estrutura de RPC (Chamada de Procedimento Remoto) de alto desempenho. O gRPC usa HTTP/2, streaming, Protobuf e contratos de mensagens para criar serviços de alto desempenho e em tempo real.

Uma limitação com gRPC é que nem todas as plataformas podem usá-la. Os navegadores não dão suporte total a HTTP/2, tornando as APIs REST e JSON a principal maneira de obter dados em aplicativos do navegador. Apesar dos benefícios que o gRPC traz, as APIs REST e JSON têm um lugar importante em aplicativos modernos. A criação de APIs Web gRPC eJSON adiciona sobrecarga indesejada ao desenvolvimento de aplicativos.

Este documento discute como criar APIs da Web JSON usando serviços gRPC.

Visão geral

A transcodificação JSON de gRPC é uma extensão para ASP.NET Core que cria APIs RESTful JSON completas para serviços gRPC. Depois de configurada, a transcodificação permite que os aplicativos chamem serviços gRPC com conceitos HTTP conhecidos:

  • Verbos HTTP
  • Associação do parâmetro de URL
  • Solicitações/respostas JSON

O gRPC ainda pode ser usado para chamar serviços.

Observação

A transcodificação gRPC JSON substitui a API HTTP gRPC, uma extensão experimental alternativa.

Uso

  1. Adicione uma referência de pacote para Microsoft.AspNetCore.Grpc.JsonTranscoding.
  2. Registre a transcodificação no código de inicialização do servidor adicionando AddJsonTranscoding : No arquivo Program.cs, altere builder.Services.AddGrpc(); para builder.Services.AddGrpc().AddJsonTranscoding();.
  3. Crie a estrutura de diretório /google/api no diretório do projeto que contém o arquivo .csproj.
  4. Adicione arquivos google/api/http.proto e google/api/annotations.proto ao diretório /google/api.
  5. Anote os métodos gRPC em seus arquivos .proto com associações HTTP e rotas:
syntax = "proto3";

option csharp_namespace = "GrpcServiceTranscoding";
import "google/api/annotations.proto";

package greet;

// The greeting service definition.
service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      get: "/v1/greeter/{name}"
    };
  }
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings.
message HelloReply {
  string message = 1;
}

O método gRPC SayHello agora pode ser invocado como gRPC e como uma API da Web JSON:

  • Solicitação: GET /v1/greeter/world
  • Resposta: { "message": "Hello world" }

Se o servidor estiver configurado para gravar logs para cada solicitação, os logs do servidor mostrarão que um serviço gRPC executa a chamada HTTP. A transcodificação mapeia a solicitação HTTP de entrada para uma mensagem gRPC e converte a mensagem de resposta em JSON.

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET https://localhost:5001/v1/greeter/world
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint 'gRPC - /v1/greeter/{name}'
info: Server.GreeterService[0]
      Sending hello to world
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint 'gRPC - /v1/greeter/{name}'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 1.996ms 200 application/json

Anotar métodos gRPC

Os métodos gRPC devem ser anotados com uma regra HTTP antes de dar suporte à transcodificação. A regra HTTP inclui informações sobre como chamar o método gRPC, como o método HTTP e a rota.

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      get: "/v1/greeter/{name}"
    };
  }
}

O exemplo de continuação:

  • Define um serviço Greeter com um método SayHello. O método tem uma regra HTTP especificada usando o nome google.api.http.
  • O método é acessível com solicitações GET e a rota /v1/greeter/{name}.
  • O campo name na mensagem de solicitação está associado a um parâmetro de rota.

Muitas opções estão disponíveis para personalizar como um método gRPC se associa a uma API RESTful. Para obter mais informações sobre como anotar métodos gRPC e personalizar JSON, consulte Configurar HTTP e JSON para transcodificação gRPC JSON.

Métodos de streaming

O gRPC tradicional por HTTP/2 dá suporte ao streaming em todas as direções. A transcodificação é limitada apenas ao streaming de servidor. Não há suporte para streaming de cliente e métodos de streaming bidirecional.

Os métodos de streaming de servidor usam JSON delimitado por linha. Cada mensagem escrita usando WriteAsync é serializada para JSON e seguida por uma nova linha.

O seguinte método de streaming de servidor grava três mensagens:

public override async Task StreamingFromServer(ExampleRequest request,
    IServerStreamWriter<ExampleResponse> responseStream, ServerCallContext context)
{
    for (var i = 1; i <= 3; i++)
    {
        await responseStream.WriteAsync(new ExampleResponse { Text = $"Message {i}" });
        await Task.Delay(TimeSpan.FromSeconds(1));
    }
}

O cliente recebe três objetos JSON delimitados por linha:

{"Text":"Message 1"}
{"Text":"Message 2"}
{"Text":"Message 3"}

Observe que a configuração WriteIndentedJSON não se aplica aos métodos de streaming de servidor. A reformatação automática adiciona novas linhas e espaço em branco a JSON, que não podem ser usadas com JSON delimitado por linha.

Veja ou baixe uma amostra de aplicativo de transcodificação e streaming gPRC do ASP.NET Core.

Protocolo HTTP

O modelo de serviço gRPC do ASP.NET Core, incluído no SDK do .NET, cria um aplicativo configurado apenas para HTTP/2. O HTTP/2 é um bom padrão quando um aplicativo dá suporte apenas ao gRPC tradicional por HTTP/2. A transcodificação, no entanto, funciona com HTTP/1.1 e HTTP/2. Algumas plataformas, como UWP ou Unity, não podem usar HTTP/2. Para dar suporte a todos os aplicativos cliente, configure o servidor para habilitar HTTP/1.1 e HTTP/2.

Atualize o protocolo padrão em appsettings.json:

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1AndHttp2"
    }
  }
}

Como alternativa, configure pontos de extremidade Kestrel no código de inicialização.

A habilitação de HTTP/1.1 e HTTP/2 na mesma porta requer TLS para negociação de protocolo. Para obter mais informações sobre como configurar protocolos HTTP em um aplicativo gRPC, consulte Negociação de protocolo gRPC do ASP.NET Core.

Transcodificação gRPC JSON vs gRPC-Web

A transcodificação e a gRPC-Web permitem que os serviços gRPC sejam chamados de um navegador. No entanto, a maneira como cada um faz isso é diferente:

  • O gRPC-Web permite que aplicativos de navegador chamem serviços gRPC do navegador com o cliente gRPC-Web e o Protobuf. O gRPC-Web requer que o aplicativo do navegador gere um cliente gRPC e tem a vantagem de enviar mensagens de Protobuf pequenas e rápidas.
  • A transcodificação permite que os aplicativos do navegador chamem serviços gRPC como se fossem APIs RESTful com JSON. O aplicativo do navegador não precisa gerar um cliente gRPC nem saber nada sobre gRPC.

O serviço Greeter anterior pode ser chamado usando APIs JavaScript do navegador:

var name = nameInput.value;

fetch('/v1/greeter/' + name)
  .then((response) => response.json())
  .then((result) => {
    console.log(result.message);
    // Hello world
  });

grpc-gateway

grpc-gateway é outra tecnologia para criar APIs RESTful JSON de serviços gRPC. Ele usa as mesmas anotações .proto para mapear conceitos HTTP para serviços gRPC.

grpc-gateway usa a geração de código para criar um servidor proxy reverso. O proxy reverso converte chamadas RESTful em gRPC+Protobuf e envia as chamadas por HTTP/2 para o serviço gRPC. O benefício dessa abordagem é que o serviço gRPC não sabe sobre as APIs RESTful JSON. Qualquer servidor gRPC pode usar grpc-gateway.

Enquanto isso, a transcodificação gRPC JSON é executada dentro de um aplicativo ASP.NET Core. Ele desserializa JSON em mensagens de Protobuf e invoca o serviço gRPC diretamente. A transcodificação em ASP.NET Core oferece vantagens para os desenvolvedores de aplicativos .NET:

  • Menos complexo: os serviços gRPC e a API RESTful JSON mapeada são executados em um aplicativo ASP.NET Core.
  • Melhor desempenho: a transcodificação desserializa JSON para mensagens de Protobuf e invoca o serviço gRPC diretamente. Há benefícios significativos de desempenho em fazer isso em processo em vez de fazer uma nova chamada gRPC para um servidor diferente.
  • Custo mais baixo: menos servidores resultam em uma conta de hospedagem mensal menor.

Para instalação e uso do grpc-gateway, consulte o LEIAME grpc-gateway.

Recursos adicionais