Integración de la fábrica de cliente de gRPC en .NET
La integración de gRPC con HttpClientFactory ofrece una manera centralizada de crear clientes gRPC. Se puede usar como alternativa a la configuración de instancias de cliente de gRPC independientes. La integración de fábrica está disponible en el paquete NuGet Grpc.Net.ClientFactory.
La fábrica ofrece las ventajas siguientes:
- Proporciona una ubicación central para configurar instancias de cliente de gRPC.
- Administra la duración del objeto
HttpClientMessageHandlersubyacente. - Propagación automática de la fecha límite y la cancelación en un servicio gRPC de ASP.NET Core
Registro de clientes gRPC
Para registrar un cliente gRPC, se puede usar el método de extensión genérico AddGrpcClient dentro de Startup.ConfigureServices, y especificar la clase del cliente con tipo de gRPC y la dirección del servicio:
services.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
});
El tipo de cliente gRPC se registra como transitorio con la inserción de dependencias (DI). Ahora el cliente se puede insertar y consumir directamente en los tipos creados por inserción de dependencias. Los controladores de ASP.NET Core MVC, los concentradores de SignalR y los servicios gRPC son lugares en los que se pueden insertar clientes gRPC de forma automática:
public class AggregatorService : Aggregator.AggregatorBase
{
private readonly Greeter.GreeterClient _client;
public AggregatorService(Greeter.GreeterClient client)
{
_client = client;
}
public override async Task SayHellos(HelloRequest request,
IServerStreamWriter<HelloReply> responseStream, ServerCallContext context)
{
// Forward the call on to the greeter service
using (var call = _client.SayHellos(request))
{
await foreach (var response in call.ResponseStream.ReadAllAsync())
{
await responseStream.WriteAsync(response);
}
}
}
}
Configuración de HttpHandler
HttpClientFactory crea el objeto HttpMessageHandler que usa el cliente gRPC. Se pueden usar métodos HttpClientFactory estándar para agregar middleware de solicitud de salida o para configurar el objeto HttpClientHandler subyacente de HttpClient:
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(LoadCertificate());
return handler;
});
Para obtener más información, vea Realización de solicitudes HTTP con IHttpClientFactory.
Configuración del canal y los interceptores
Hay métodos específicos de gRPC disponibles para:
- Configurar el canal subyacente de un cliente gRPC.
- Agregar instancias de
Interceptorque el cliente usará al realizar llamadas a gRPC.
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.AddInterceptor(() => new LoggingInterceptor())
.ConfigureChannel(o =>
{
o.Credentials = new CustomCredentials();
});
Un interceptor de gRPC o credenciales de canal pueden usarse para enviar metadatos Authorization con cada solicitud. Para obtener más información sobre cómo configurar la autenticación, consulte la sección sobre cómo enviar un token de portador con la fábrica de cliente de gRPC.
Propagación de la fecha límite y la cancelación
Los clientes gRPC creados por la fábrica en un servicio gRPC se pueden configurar con EnableCallContextPropagation() para propagar automáticamente la fecha límite y el token de cancelación a las llamadas secundarias. El método de extensión EnableCallContextPropagation() está disponible en el paquete NuGet Grpc.AspNetCore.Server.ClientFactory.
La propagación del contexto de llamada funciona mediante la lectura de la fecha límite y el token de cancelación del contexto de solicitud gRPC actual y su propagación automática a las llamadas salientes realizadas por el cliente gRPC. La propagación del contexto de llamada es una excelente manera de garantizar que los escenarios complejos de gRPC anidados siempre propagan la fecha límite y la cancelación.
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.EnableCallContextPropagation();
De forma predeterminada, EnableCallContextPropagation genera un error si el cliente se usa fuera del contexto de una llamada a gRPC. El error se ha diseñado para avisarle de que no hay un contexto de llamada que propagar. Si desea utilizar el cliente fuera de un contexto de llamada, suprima el error cuando el cliente esté configurado con SuppressContextNotFoundErrors:
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.EnableCallContextPropagation(o => o.SuppressContextNotFoundErrors = true);
Para obtener más información sobre las fechas límite y la cancelación de RPC, vea Servicios gRPC confiables con fechas límite y cancelación.
Clientes con nombre
Normalmente, un tipo de cliente gRPC se registra una vez y, a continuación, se inserta directamente en el constructor de un tipo mediante DI. Sin embargo, hay escenarios en los que resulta útil tener varias configuraciones para un cliente. Por ejemplo, un cliente que realiza llamadas gRPC con y sin autenticación.
Para registrar varios clientes con el mismo tipo, asigne un nombre a cada cliente. Cada cliente con nombre puede tener su propia configuración. El método de extensión AddGrpcClient genérico tiene una sobrecarga que incluye un parámetro de nombre:
services
.AddGrpcClient<Greeter.GreeterClient>("Greeter", o =>
{
o.Address = new Uri("https://localhost:5001");
});
services
.AddGrpcClient<Greeter.GreeterClient>("GreeterAuthenticated", o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigureChannel(o =>
{
o.Credentials = new CustomCredentials();
});
El código anterior:
- Registra el tipo
GreeterClientdos veces, especificando un nombre único cada vez. - Configura diferentes opciones para cada cliente con nombre. El registro
GreeterAuthenticatedagrega credenciales al canal para que se autentiquen las llamadas gRPC realizadas con él.
Se crea un cliente gRPC con nombre en el código de la aplicación mediante GrpcClientFactory. El tipo y el nombre del cliente deseado se especifican mediante el método GrpcClientFactory.CreateClient genérico:
public class AggregatorService : Aggregator.AggregatorBase
{
private readonly Greeter.GreeterClient _client;
public AggregatorService(GrpcClientFactory grpcClientFactory)
{
_client = grpcClientFactory.CreateClient<Greeter.GreeterClient>("GreeterAuthenticated");
}
}