Tích hợp gRPC client factory trong .NET
gRPC tích hợp với HttpClientFactory cung cấp một cách tập trung để tạo gRPC client. Nó có thể được sử dụng như một giải pháp thay thế cho cấu hình các instance gRPC client độc lập. Factory integration (tích hợp factory) có sẵn trong gói NuGet Grpc.Net.ClientFactory.
Factory cung cấp các lợi ích sau:
- Cung cấp một vị trí tập trung để cấu hình các instance gRPC client logic.
- Quản lý lifetime (vòng đời) của
HttpClientMessageHandlerbên dưới. - Tự động propagation (truyền) deadline và cancellation trong dịch vụ gRPC ASP.NET Core.
Đăng ký gRPC client
Để đăng ký gRPC client, extension method generic AddGrpcClient có thể được sử dụng trong instance của WebApplicationBuilder tại điểm đầu vào của ứng dụng trong Program.cs, chỉ định class gRPC typed client và địa chỉ dịch vụ:
builder.Services.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
});Kiểu gRPC client được đăng ký là transient với dependency injection (DI). Client giờ đây có thể được inject và sử dụng trực tiếp trong các kiểu được tạo bởi DI. ASP.NET Core MVC controllers, SignalR hubs và dịch vụ gRPC là những nơi gRPC client có thể được inject tự động:
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);
}
}
}
}Cấu hình HttpHandler
HttpClientFactory tạo ra HttpMessageHandler được sử dụng bởi gRPC client. Các phương thức HttpClientFactory tiêu chuẩn có thể được dùng để thêm outgoing request middleware (phần mềm trung gian request đi) hoặc cấu hình HttpClientHandler bên dưới của HttpClient:
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(LoadCertificate());
return handler;
});Để biết thêm thông tin, xem Make HTTP requests using IHttpClientFactory.
Cấu hình Interceptors (bộ chặn)
gRPC interceptors có thể được thêm vào client bằng phương thức AddInterceptor.
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.AddInterceptor<LoggingInterceptor>();Code trước đó:
- Đăng ký kiểu
GreeterClient. - Cấu hình một
LoggingInterceptorcho client này.LoggingInterceptorđược tạo một lần và chia sẻ giữa các instanceGreeterClient.
Theo mặc định, một interceptor được tạo một lần và chia sẻ giữa các client. Hành vi này có thể được ghi đè bằng cách chỉ định scope khi đăng ký interceptor. Client factory có thể được cấu hình để tạo interceptor mới cho mỗi client bằng cách chỉ định InterceptorScope.Client.
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.AddInterceptor<LoggingInterceptor>(InterceptorScope.Client);Việc tạo interceptor có phạm vi client hữu ích khi interceptor yêu cầu các dịch vụ có phạm vi scoped hoặc transient từ DI.
Một interceptor gRPC hoặc channel credentials có thể được sử dụng để gửi metadata Authorization với mỗi request. Để biết thêm thông tin về cách cấu hình authentication (xác thực), xem Send a bearer token with gRPC client factory.
Cấu hình Channel
Cấu hình bổ sung có thể được áp dụng cho channel bằng phương thức ConfigureChannel:
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigureChannel(o =>
{
o.Credentials = new CustomCredentials();
});ConfigureChannel được truyền một instance GrpcChannelOptions. Để biết thêm thông tin, xem configure client options.
Một số thuộc tính được thiết lập trên GrpcChannelOptions trước khi callback ConfigureChannel chạy:
- HttpHandler được thiết lập thành kết quả từ ConfigurePrimaryHttpMessageHandler.
- LoggerFactory được thiết lập thành ILoggerFactory được resolve từ DI.
Các giá trị này có thể được ghi đè bởi ConfigureChannel.
Call credentials (thông tin xác thực lời gọi)
Authentication header có thể được thêm vào lời gọi gRPC bằng phương thức AddCallCredentials:
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.AddCallCredentials((context, metadata) =>
{
if (!string.IsNullOrEmpty(_token))
{
metadata.Add("Authorization", $"Bearer {_token}");
}
return Task.CompletedTask;
});Để biết thêm thông tin về cách cấu hình call credentials, xem Bearer token with gRPC client factory.
Propagation deadline và cancellation
gRPC client được tạo bởi factory trong dịch vụ gRPC có thể được cấu hình với EnableCallContextPropagation() để tự động propagate (truyền) deadline và cancellation token đến các lời gọi con. Extension method EnableCallContextPropagation() có sẵn trong gói NuGet Grpc.AspNetCore.Server.ClientFactory.
Call context propagation (truyền ngữ cảnh lời gọi) hoạt động bằng cách đọc deadline và cancellation token từ ngữ cảnh request gRPC hiện tại và tự động propagate chúng đến các lời gọi đi do gRPC client thực hiện. Call context propagation là cách tuyệt vời để đảm bảo rằng các kịch bản gRPC phức tạp, lồng nhau luôn propagate deadline và cancellation.
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.EnableCallContextPropagation();Theo mặc định, EnableCallContextPropagation gây ra lỗi nếu client được sử dụng bên ngoài ngữ cảnh của lời gọi gRPC. Lỗi được thiết kế để cảnh báo bạn rằng không có call context để propagate. Nếu bạn muốn sử dụng client bên ngoài call context, hãy suppress (bỏ qua) lỗi khi client được cấu hình với SuppressContextNotFoundErrors:
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.EnableCallContextPropagation(o => o.SuppressContextNotFoundErrors = true);Để biết thêm thông tin về deadline và RPC cancellation, xem Reliable gRPC services with deadlines and cancellation.
Named clients (client được đặt tên)
Thông thường, một kiểu gRPC client được đăng ký một lần và sau đó được inject trực tiếp vào constructor của kiểu bởi DI. Tuy nhiên, có những tình huống mà việc có nhiều cấu hình cho một client là hữu ích. Ví dụ, client thực hiện lời gọi gRPC có và không có authentication.
Nhiều client cùng kiểu có thể được đăng ký bằng cách đặt tên cho mỗi client. Mỗi named client có thể có cấu hình riêng của nó. Extension method generic AddGrpcClient có overload bao gồm tham số name:
builder.Services
.AddGrpcClient<Greeter.GreeterClient>("Greeter", o =>
{
o.Address = new Uri("https://localhost:5001");
});
builder.Services
.AddGrpcClient<Greeter.GreeterClient>("GreeterAuthenticated", o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigureChannel(o =>
{
o.Credentials = new CustomCredentials();
});Code trước đó:
- Đăng ký kiểu
GreeterClienthai lần, chỉ định tên duy nhất cho mỗi. - Cấu hình các cài đặt khác nhau cho mỗi named client. Đăng ký
GreeterAuthenticatedthêm credentials vào channel để các lời gọi gRPC được thực hiện với nó được xác thực.
Named gRPC client được tạo trong app code sử dụng GrpcClientFactory. Kiểu và tên của client mong muốn được chỉ định bằng phương thức generic GrpcClientFactory.CreateClient:
public class AggregatorService : Aggregator.AggregatorBase
{
private readonly Greeter.GreeterClient _client;
public AggregatorService(GrpcClientFactory grpcClientFactory)
{
_client = grpcClientFactory.CreateClient<Greeter.GreeterClient>("GreeterAuthenticated");
}
}