Servicios gRPC con ASP.NET Core

En este documento se muestra cómo empezar a usar servicios gRPC con ASP.NET Core.

Advertencia

ASP.NET Core gRPC tiene requisitos adicionales para su uso con Azure App Service o IIS. Para obtener más información sobre dónde se puede usar gRPC, vea gRPC en plataformas compatibles con .NET.

Requisitos previos

Introducción al servicio gRPC en ASP.NET Core

Vea o descargue el código de ejemplo (cómo descargarlo).

Consulte el artículo Introducción a los servicios gRPC para obtener instrucciones detalladas sobre cómo crear un proyecto gRPC.

Incorporación de servicios gRPC a una aplicación de ASP.NET Core

gRPC requiere el paquete Grpc.AspNetCore.

Configuración de gRPC

En Startup.cs:

  • gRPC se habilita con el método AddGrpc.
  • Cada servicio gRPC se agrega a la canalización de enrutamiento a través del método MapGrpcService.
public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddGrpc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            // 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
            endpoints.MapGrpcService<GreeterService>();
        });
    }
}

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.

El middleware y las características de ASP.NET Core comparten la canalización de enrutamiento, por lo que se puede configurar una aplicación para que preste servicio a controladores de solicitudes adicionales. Los controladores de solicitudes adicionales, como los controladores MVC, trabajan en paralelo con los servicios gRPC configurados.

Opciones de servidor

Los servicios gRPC se pueden hospedar por todos los servidores de ASP.NET Core integrados.

  • Kestrel
  • TestServer
  • IIS†
  • HTTP.sys‡

†IIS requiere .NET 5 y Windows 10, compilación 20300.1000 o posterior.
‡HTTP.sys requiere .NET 5 y Windows 10, compilación 19529 o posterior.

Las versiones de la compilación de Windows 10 anteriores pueden requerir el uso de una compilación para Windows Insider.

Para obtener más información sobre cómo elegir el servidor adecuado para una aplicación ASP.NET Core, vea Implementaciones de servidores web en ASP.NET Core.

Kestrel

Kestrel es un servidor web multiplataforma de ASP.NET Core. Kestrel proporciona el mejor rendimiento y uso de memoria, pero carece de algunas de las características avanzadas de HTTP.sys (como el uso compartido de puertos).

Puntos de conexión gRPC de Kestrel:

HTTP/2

gRPC requiere HTTP/2. gRPC para ASP.NET Core valida que HttpRequest.Protocol sea HTTP/2.

Kestrel admite HTTP/2 en la mayoría de los sistemas operativos modernos. Los puntos de conexión de Kestrel se configuran para admitir conexiones HTTP/1.1 y HTTP/2 de forma predeterminada.

TLS

Los puntos de conexión de Kestrel usados para gRPC deben protegerse con TLS. En la fase de desarrollo, se crea automáticamente un punto de conexión protegido con TLS en https://localhost:5001 cuando el certificado de desarrollo de ASP.NET Core está presente. No se requiere ninguna configuración. Un prefijo https comprueba que el punto de conexión de Kestrel está usando TLS.

En un entorno de producción, se debe configurar TLS explícitamente. En el siguiente ejemplo de appsettings.json , se proporciona un punto de conexión HTTP/2 protegido con TLS:

{
  "Kestrel": {
    "Endpoints": {
      "HttpsInlineCertFile": {
        "Url": "https://localhost:5001",
        "Protocols": "Http2",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "<certificate password>"
        }
      }
    }
  }
}

Como alternativa, se pueden configurar puntos de conexión de Kestrel en Program.cs:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.ConfigureKestrel(options =>
            {
                options.Listen(IPAddress.Any, 5001, listenOptions =>
                {
                    listenOptions.Protocols = HttpProtocols.Http2;
                    listenOptions.UseHttps("<path to .pfx file>", 
                        "<certificate password>");
                });
            });
            webBuilder.UseStartup<Startup>();
        });

Para más información sobre cómo habilitar TLS con Kestrel, vea Configuración de los puntos de conexión HTTPS para Kestrel.

Negociación del protocolo

TLS no solo se usa para proteger la comunicación. El protocolo de enlace Application-Layer Protocol Negotiation (ALPN) de TLS se usa para negociar el protocolo de conexión entre el cliente y el servidor cuando un punto de conexión admite varios protocolos. Esta negociación determina si la conexión usa HTTP/1.1 o HTTP/2.

Si un punto de conexión HTTP/2 se configura sin TLS, el valor ListenOptions.Protocols del punto de conexión debe establecerse en HttpProtocols.Http2. No se puede usar un punto de conexión con varios protocolos (por ejemplo, HttpProtocols.Http1AndHttp2) sin TLS, porque no hay ninguna negociación. Se usa HTTP/1.1 de forma predeterminada para todas las conexiones al punto de conexión no seguro y se produce un error en las llamadas a gRPC.

Para obtener más información sobre cómo habilitar HTTP/2 y TLS con Kestrel, consulte la sección sobre la configuración del punto de conexión de Kestrel.

Nota

macOS no admite gRPC de ASP.NET Core con TLS. Se requiere configuración adicional para ejecutar correctamente servicios gRPC en macOS. Para obtener más información, vea No se puede iniciar la aplicación gRPC de ASP.NET Core en macOS.

IIS

Internet Information Services (IIS) es un servidor web flexible, seguro y administrable para el hospedaje de aplicaciones web, incluido ASP.NET Core. Se necesitan .NET 5 y la compilación 20300.1000, o versiones posteriores, de Windows 10, para hospedar los servicios gRPC con IIS, lo que puede requerir el uso de una compilación para Windows Insider.

IIS debe estar configurado para usar TLS y HTTP/2. Para obtener más información, vea Uso de ASP.NET Core con HTTP/2 en IIS.

HTTP.sys

HTTP.sys es un servidor web de ASP.NET Core que solo se ejecuta en Windows. Se necesitan .NET 5 y la compilación 19529, o versiones posteriores, de Windows 10 para hospedar los servicios gRPC con HTTP.sys, lo que puede requerir el uso de una compilación para Windows Insider.

HTTP.sys debe estar configurado para usar TLS y HTTP/2. Para obtener más información, vea Compatibilidad con HTTP/2 del servidor web HTTP.sys.

Kestrel

Kestrel es un servidor web multiplataforma de ASP.NET Core. Kestrel proporciona el mejor rendimiento y uso de memoria, pero carece de algunas de las características avanzadas de HTTP.sys (como el uso compartido de puertos).

Puntos de conexión gRPC de Kestrel:

HTTP/2

gRPC requiere HTTP/2. gRPC para ASP.NET Core valida que HttpRequest.Protocol sea HTTP/2.

Kestrel admite HTTP/2 en la mayoría de los sistemas operativos modernos. Los puntos de conexión de Kestrel se configuran para admitir conexiones HTTP/1.1 y HTTP/2 de forma predeterminada.

TLS

Los puntos de conexión de Kestrel usados para gRPC deben protegerse con TLS. En la fase de desarrollo, se crea automáticamente un punto de conexión protegido con TLS en https://localhost:5001 cuando el certificado de desarrollo de ASP.NET Core está presente. No se requiere ninguna configuración. Un prefijo https comprueba que el punto de conexión de Kestrel está usando TLS.

En un entorno de producción, se debe configurar TLS explícitamente. En el siguiente ejemplo de appsettings.json , se proporciona un punto de conexión HTTP/2 protegido con TLS:

{
  "Kestrel": {
    "Endpoints": {
      "HttpsInlineCertFile": {
        "Url": "https://localhost:5001",
        "Protocols": "Http2",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "<certificate password>"
        }
      }
    }
  }
}

Como alternativa, se pueden configurar puntos de conexión de Kestrel en Program.cs:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.ConfigureKestrel(options =>
            {
                options.Listen(IPAddress.Any, 5001, listenOptions =>
                {
                    listenOptions.Protocols = HttpProtocols.Http2;
                    listenOptions.UseHttps("<path to .pfx file>", 
                        "<certificate password>");
                });
            });
            webBuilder.UseStartup<Startup>();
        });

Para más información sobre cómo habilitar TLS con Kestrel, vea Configuración de los puntos de conexión HTTPS para Kestrel.

Negociación del protocolo

TLS no solo se usa para proteger la comunicación. El protocolo de enlace Application-Layer Protocol Negotiation (ALPN) de TLS se usa para negociar el protocolo de conexión entre el cliente y el servidor cuando un punto de conexión admite varios protocolos. Esta negociación determina si la conexión usa HTTP/1.1 o HTTP/2.

Si un punto de conexión HTTP/2 se configura sin TLS, el valor ListenOptions.Protocols del punto de conexión debe establecerse en HttpProtocols.Http2. No se puede usar un punto de conexión con varios protocolos (por ejemplo, HttpProtocols.Http1AndHttp2) sin TLS, porque no hay ninguna negociación. Se usa HTTP/1.1 de forma predeterminada para todas las conexiones al punto de conexión no seguro y se produce un error en las llamadas a gRPC.

Para obtener más información sobre cómo habilitar HTTP/2 y TLS con Kestrel, consulte la sección sobre la configuración del punto de conexión de Kestrel.

Nota

macOS no admite gRPC de ASP.NET Core con TLS. Se requiere configuración adicional para ejecutar correctamente servicios gRPC en macOS. Para obtener más información, vea No se puede iniciar la aplicación gRPC de ASP.NET Core en macOS.

Integración con las API de ASP.NET Core

Los servicios gRPC tienen acceso total a las características de ASP.NET Core, como la inserción de dependencias (ID) y los registros. Por ejemplo, la implementación de los servicios puede resolver un servicio del registrador desde el contenedor de inserción de dependencias mediante el constructor:

public class GreeterService : Greeter.GreeterBase
{
    public GreeterService(ILogger<GreeterService> logger)
    {
    }
}

De forma predeterminada, la implementación de los servicios gRPC puede resolver otros servicios de inserción de dependencias con cualquier duración (singleton, restringida o transitoria).

Resolución de HttpContext en métodos gRPC

La API de gRPC proporciona acceso a algunos datos de mensajes HTTP/2, como el método, el host, el encabezado y los finalizadores. El acceso se realiza a través del argumento ServerCallContext que se pasa a cada método gRPC:

public class GreeterService : Greeter.GreeterBase
{
    public override Task<HelloReply> SayHello(
        HelloRequest request, ServerCallContext context)
    {
        return Task.FromResult(new HelloReply
        {
            Message = "Hello " + request.Name
        });
    }
}

ServerCallContext no proporciona acceso completo a HttpContext en todas las API de ASP.NET. Sin embargo, el método de extensión GetHttpContext sí proporciona acceso completo al objeto HttpContext que representa el mensaje HTTP/2 subyacente en las API de ASP.NET:

public class GreeterService : Greeter.GreeterBase
{
    public override Task<HelloReply> SayHello(
        HelloRequest request, ServerCallContext context)
    {
        var httpContext = context.GetHttpContext();
        var clientCertificate = httpContext.Connection.ClientCertificate;

        return Task.FromResult(new HelloReply
        {
            Message = "Hello " + request.Name + " from " + clientCertificate.Issuer
        });
    }
}

Recursos adicionales