Nguon: Microsoft Learn · .NET 8.0

Tích hợp gRPC client factory trong .NET

Nguồn: gRPC client factory integration in .NET

Bởi James Newton-King

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:

Đă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ụ:

csharp
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:

csharp
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:

csharp
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.

csharp
builder.Services
    .AddGrpcClient<Greeter.GreeterClient>(o =>
    {
        o.Address = new Uri("https://localhost:5001");
    })
    .AddInterceptor<LoggingInterceptor>();

Code trước đó:

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.

csharp
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:

csharp
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:

csharp
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.

csharp
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:

csharp
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:

csharp
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 đó:

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:

csharp
public class AggregatorService : Aggregator.AggregatorBase
{
    private readonly Greeter.GreeterClient _client;

    public AggregatorService(GrpcClientFactory grpcClientFactory)
    {
        _client = grpcClientFactory.CreateClient<Greeter.GreeterClient>("GreeterAuthenticated");
    }
}

Tài nguyên bổ sung