Servicios gRPC con C#

En este documento se describen los conceptos necesarios para escribir de aplicaciones gRPC en C#. Los temas aquí tratados son válidos para aplicaciones de gRPC basadas tanto en ASP.NET Core como en C-core.

Archivo .proto

gRPC usa un enfoque de contrato primero para el desarrollo de API. Los búferes de protocolo (Protobuf) se usan de forma predeterminada como el lenguaje de definición de interfaz (IDL). El archivo .proto contiene lo siguiente:

  • La definición del servicio gRPC
  • Los mensajes enviados entre clientes y servidores

Para más información sobre la sintaxis de los archivos de protobuf, consulte Creación de mensajes de Protobuf para aplicaciones .NET.

Vamos a considerar, por ejemplo, el archivo greeter.proto que se usa en Introducción a un servicio gRPC:

  • Define un servicio Greeter.
  • El servicio Greeter define una llamada a SayHello.
  • SayHello envía un mensaje HelloRequest y recibe un mensaje HelloReply:
syntax = "proto3";

option csharp_namespace = "GrpcGreeter";

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

Si quiere que los comentarios de código se traduzcan en más idiomas además del inglés, háganoslo saber en este problema de debate de GitHub.

Adición de un archivo .proto a una aplicación de C#

Para incluir el archivo .proto en un proyecto, hay que agregarlo al grupo de elementos <Protobuf>:

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

De forma predeterminada, una referencia <Protobuf> genera un cliente concreto y una clase base de servicio. El atributo GrpcServices del elemento de referencia se puede usar para limitar la generación de recursos de C#. Las opciones válidas de GrpcServices son:

  • Both (valor predeterminado si no se especifica)
  • Server
  • Client
  • None

Compatibilidad de las herramientas de C# con archivos .proto

El paquete de herramientas Grpc.Tools es necesario para generar los recursos de C# a partir de los archivos .proto. Los activos (archivos) generados:

  • Se generan según sea necesario cada vez que el proyecto se compila.
  • No se agregan al proyecto ni se protegen en el control de código fuente.
  • Son un artefacto de compilación contenido en el directorio obj.

Este paquete es necesario en los proyectos tanto de servidor como de cliente. El metapaquete Grpc.AspNetCore incluye una referencia a Grpc.Tools. Los proyectos de servidor pueden agregar Grpc.AspNetCore por medio del administrador de paquetes de Visual Studio, o bien agregando un elemento <PackageReference> al archivo de proyecto:

<PackageReference Include="Grpc.AspNetCore" Version="2.32.0" />

Los proyectos de cliente, por su parte, deben hacer referencia directamente a Grpc.Tools junto con los demás paquetes necesarios para usar el cliente de gRPC. El paquete de herramientas no es necesario en tiempo de ejecución, de modo que la dependencia se marca con PrivateAssets="All":

<PackageReference Include="Google.Protobuf" Version="3.18.0" />
<PackageReference Include="Grpc.Net.Client" Version="2.52.0" />
<PackageReference Include="Grpc.Tools" Version="2.40.0">
  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
  <PrivateAssets>all</PrivateAssets>
</PackageReference>

Activos de C# generados

El paquete de herramientas genera los tipos de C# que representan los mensajes definidos en los archivos .proto incluidos.

En el caso de los activos del lado servidor, se genera un tipo base de servicio abstracto. El tipo base contiene las definiciones de todas las llamadas a gRPC contenidas en el archivo .proto. Cree una implementación de servicio concreta que se derive de este tipo base e implemente la lógica de las llamadas a gRPC. Respecto a greet.proto, el ejemplo descrito anteriormente, se genera un tipo de elemento GreeterBase abstracto que contiene un método SayHello virtual. Una elemento GreeterService de una implementación concreta invalida el método e implementa la lógica que controla la llamada de gRPC.

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

En cuanto a los activos del lado cliente, se genera un tipo de cliente concreto. Las llamadas de gRPC en el archivo .proto se traducen en métodos en el tipo concreto a los que se puede llamar. Respecto a greet.proto, el ejemplo descrito anteriormente, se genera un tipo de elemento GreeterClient concreto. Llame a GreeterClient.SayHelloAsync para iniciar una llamada de gRPC al servidor.

// The port number must match the port of the gRPC server.
using var channel = GrpcChannel.ForAddress("https://localhost:7042");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
                  new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();

De forma predeterminada, se generan recursos de servidor y de cliente para cada archivo .proto incluido en el grupo de elementos <Protobuf>. Para garantizar que solo se generan activos de servidor en un proyecto de servidor, el atributo GrpcServices se establece en Server.

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

Y lo mismo sucede en los proyectos de cliente, donde el atributo se establece en Client.

Recursos adicionales

En este documento se describen los conceptos necesarios para escribir de aplicaciones gRPC en C#. Los temas aquí tratados son válidos para aplicaciones de gRPC basadas tanto en ASP.NET Core como en C-core.

Archivo .proto

gRPC usa un enfoque de contrato primero para el desarrollo de API. Los búferes de protocolo (Protobuf) se usan de forma predeterminada como el lenguaje de definición de interfaz (IDL). El archivo .proto contiene lo siguiente:

  • La definición del servicio gRPC
  • Los mensajes enviados entre clientes y servidores

Para más información sobre la sintaxis de los archivos de protobuf, consulte Creación de mensajes de Protobuf para aplicaciones .NET.

Vamos a considerar, por ejemplo, el archivo greeter.proto que se usa en Introducción a un servicio gRPC:

  • Define un servicio Greeter.
  • El servicio Greeter define una llamada a SayHello.
  • SayHello envía un mensaje HelloRequest y recibe un mensaje HelloReply:
syntax = "proto3";

option csharp_namespace = "GrpcGreeter";

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

Si quiere que los comentarios de código se traduzcan en más idiomas además del inglés, háganoslo saber en este problema de debate de GitHub.

Adición de un archivo .proto a una aplicación de C#

Para incluir el archivo .proto en un proyecto, hay que agregarlo al grupo de elementos <Protobuf>:

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

De forma predeterminada, una referencia <Protobuf> genera un cliente concreto y una clase base de servicio. El atributo GrpcServices del elemento de referencia se puede usar para limitar la generación de recursos de C#. Las opciones válidas de GrpcServices son:

  • Both (valor predeterminado si no se especifica)
  • Server
  • Client
  • None

Compatibilidad de las herramientas de C# con archivos .proto

El paquete de herramientas Grpc.Tools es necesario para generar los recursos de C# a partir de los archivos .proto. Los activos (archivos) generados:

  • Se generan según sea necesario cada vez que el proyecto se compila.
  • No se agregan al proyecto ni se protegen en el control de código fuente.
  • Son un artefacto de compilación contenido en el directorio obj.

Este paquete es necesario en los proyectos tanto de servidor como de cliente. El metapaquete Grpc.AspNetCore incluye una referencia a Grpc.Tools. Los proyectos de servidor pueden agregar Grpc.AspNetCore por medio del administrador de paquetes de Visual Studio, o bien agregando un elemento <PackageReference> al archivo de proyecto:

<PackageReference Include="Grpc.AspNetCore" Version="2.28.0" />

Los proyectos de cliente, por su parte, deben hacer referencia directamente a Grpc.Tools junto con los demás paquetes necesarios para usar el cliente de gRPC. El paquete de herramientas no es necesario en tiempo de ejecución, de modo que la dependencia se marca con PrivateAssets="All":

<PackageReference Include="Google.Protobuf" Version="3.11.4" />
<PackageReference Include="Grpc.Net.Client" Version="2.52.0" />
<PackageReference Include="Grpc.Tools" Version="2.28.1">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

Activos de C# generados

El paquete de herramientas genera los tipos de C# que representan los mensajes definidos en los archivos .proto incluidos.

En el caso de los activos del lado servidor, se genera un tipo base de servicio abstracto. El tipo base contiene las definiciones de todas las llamadas a gRPC contenidas en el archivo .proto. Cree una implementación de servicio concreta que se derive de este tipo base e implemente la lógica de las llamadas a gRPC. Respecto a greet.proto, el ejemplo descrito anteriormente, se genera un tipo de elemento GreeterBase abstracto que contiene un método SayHello virtual. Una elemento GreeterService de una implementación concreta invalida el método e implementa la lógica que controla la llamada de gRPC.

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

En cuanto a los activos del lado cliente, se genera un tipo de cliente concreto. Las llamadas de gRPC en el archivo .proto se traducen en métodos en el tipo concreto a los que se puede llamar. Respecto a greet.proto, el ejemplo descrito anteriormente, se genera un tipo de elemento GreeterClient concreto. Llame a GreeterClient.SayHelloAsync para iniciar una llamada de gRPC al servidor.

static async Task Main(string[] args)
{
    // The port number(5001) must match the port of the gRPC server.
    using var channel = GrpcChannel.ForAddress("https://localhost:5001");
    var client = new Greeter.GreeterClient(channel);
    var reply = await client.SayHelloAsync(
                      new HelloRequest { Name = "GreeterClient" });
    Console.WriteLine("Greeting: " + reply.Message);
    Console.WriteLine("Press any key to exit...");
    Console.ReadKey();
}

De forma predeterminada, se generan recursos de servidor y de cliente para cada archivo .proto incluido en el grupo de elementos <Protobuf>. Para garantizar que solo se generan activos de servidor en un proyecto de servidor, el atributo GrpcServices se establece en Server.

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

Y lo mismo sucede en los proyectos de cliente, donde el atributo se establece en Client.

Recursos adicionales