Integrasi pabrik klien gRPC di .NET

Oleh James Newton-King

Integrasi gRPC dengan HttpClientFactory menawarkan cara terpusat untuk membuat klien gRPC. Ini dapat digunakan sebagai alternatif untuk mengonfigurasi instans klien gRPC yang berdiri sendiri. Integrasi pabrik tersedia dalam paket Grpc.Net.ClientFactory NuGet.

Pabrik menawarkan manfaat berikut:

  • Menyediakan lokasi pusat untuk mengonfigurasi instans klien gRPC logis.
  • Mengelola masa pakai yang mendasari HttpClientMessageHandler.
  • Penyebaran tenggat waktu dan pembatalan otomatis dalam layanan gRPC core ASP.NET.

Mendaftarkan klien gRPC

Untuk mendaftarkan klien gRPC, metode ekstensi generik AddGrpcClient dapat digunakan dalam instans WebApplicationBuilder di titik masuk aplikasi di , menentukan kelas klien yang di Program.csketik gRPC dan alamat layanan:

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

Jenis klien gRPC terdaftar sebagai sementara dengan injeksi dependensi (DI). Klien sekarang dapat disuntikkan dan dikonsumsi langsung dalam jenis yang dibuat oleh DI. ASP.NET pengontrol Core MVC, hub, SignalR dan layanan gRPC adalah tempat di mana klien gRPC dapat secara otomatis disuntikkan:

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

Mengonfigurasi HttpHandler

HttpClientFactory membuat yang HttpMessageHandler digunakan oleh klien gRPC. Metode standar HttpClientFactory dapat digunakan untuk menambahkan middleware permintaan keluar atau untuk mengonfigurasi dasar HttpClientHandlerHttpClientdari :

builder.Services
    .AddGrpcClient<Greeter.GreeterClient>(o =>
    {
        o.Address = new Uri("https://localhost:5001");
    })
    .ConfigurePrimaryHttpMessageHandler(() =>
    {
        var handler = new HttpClientHandler();
        handler.ClientCertificates.Add(LoadCertificate());
        return handler;
    });

Untuk informasi selengkapnya, lihat Membuat permintaan HTTP menggunakan IHttpClientFactory.

Mengonfigurasi Interceptors

Pencegat gRPC dapat ditambahkan ke klien menggunakan metode .AddInterceptor

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

Kode sebelumnya:

  • Mendaftarkan jenis.GreeterClient
  • LoggingInterceptor Mengonfigurasi untuk klien ini. LoggingInterceptor dibuat sekali dan dibagikan antar GreeterClient instans.

Secara default, pencegat dibuat sekali dan dibagikan antar klien. Perilaku ini dapat ditimpa dengan menentukan cakupan saat mendaftarkan pencegat. Pabrik klien dapat dikonfigurasi untuk membuat pencegat baru untuk setiap klien dengan menentukan InterceptorScope.Client.

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

Membuat pencegat cakupan klien berguna ketika pencegat memerlukan layanan cakupan atau sementara dari DI.

Pencegat gRPC atau kredensial saluran dapat digunakan untuk mengirim Authorization metadata dengan setiap permintaan. Untuk informasi selengkapnya tentang mengonfigurasi autentikasi, lihat Mengirim token pembawa dengan pabrik klien gRPC.

Mengonfigurasi Saluran

Konfigurasi tambahan dapat diterapkan ke saluran menggunakan ConfigureChannel metode :

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

ConfigureChannel diteruskan instans GrpcChannelOptions . Untuk informasi selengkapnya, lihat mengonfigurasi opsi klien.

Catatan

Beberapa properti diatur pada GrpcChannelOptions sebelum ConfigureChannel panggilan balik dijalankan:

Nilai-nilai ini dapat ditimpa oleh ConfigureChannel.

Kredensial panggilan

Header autentikasi dapat ditambahkan ke panggilan gRPC menggunakan AddCallCredentials metode :

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

Untuk informasi selengkapnya tentang mengonfigurasi kredensial panggilan, lihat Token pembawa dengan pabrik klien gRPC.

Tenggat waktu dan penyebaran pembatalan

Klien gRPC yang dibuat oleh pabrik dalam layanan gRPC dapat dikonfigurasi dengan EnableCallContextPropagation() untuk secara otomatis menyebarluaskan tenggat waktu dan token pembatalan ke panggilan anak. Metode EnableCallContextPropagation() ekstensi tersedia dalam paket NuGet Grpc.AspNetCore.Server.ClientFactory .

Propagasi konteks panggilan berfungsi dengan membaca tenggat waktu dan token pembatalan dari konteks permintaan gRPC saat ini dan secara otomatis menyebarkannya ke panggilan keluar yang dilakukan oleh klien gRPC. Penyebaran konteks panggilan adalah cara yang sangat baik untuk memastikan bahwa skenario gRPC yang kompleks dan berlapis selalu menyebarluaskan tenggat waktu dan pembatalan.

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

Secara default, EnableCallContextPropagation menimbulkan kesalahan jika klien digunakan di luar konteks panggilan gRPC. Kesalahan dirancang untuk memberi tahu Anda bahwa tidak ada konteks panggilan untuk disebarluaskan. Jika Anda ingin menggunakan klien di luar konteks panggilan, tekan kesalahan saat klien dikonfigurasi dengan SuppressContextNotFoundErrors:

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

Untuk informasi selengkapnya tentang tenggat waktu dan pembatalan RPC, lihat Layanan gRPC andal dengan tenggat waktu dan pembatalan.

Klien bernama

Biasanya, jenis klien gRPC didaftarkan sekali dan kemudian disuntikkan langsung ke konstruktor jenis oleh DI. Namun, ada skenario di mana berguna untuk memiliki beberapa konfigurasi untuk satu klien. Misalnya, klien yang melakukan panggilan gRPC dengan dan tanpa autentikasi.

Beberapa klien dengan jenis yang sama dapat didaftarkan dengan memberi nama kepada setiap klien. Setiap klien bernama dapat memiliki konfigurasinya sendiri. Metode ekstensi generik AddGrpcClient memiliki kelebihan beban yang menyertakan parameter nama:

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

Kode sebelumnya:

  • Mendaftarkan GreeterClient jenis dua kali, menentukan nama unik untuk masing-masing.
  • Mengonfigurasi pengaturan yang berbeda untuk setiap klien bernama. Pendaftaran GreeterAuthenticated menambahkan kredensial ke saluran sehingga panggilan gRPC yang dilakukan dengannya diautentikasi.

Klien gRPC bernama dibuat dalam kode aplikasi menggunakan GrpcClientFactory. Jenis dan nama klien yang diinginkan ditentukan menggunakan metode generik GrpcClientFactory.CreateClient :

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

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

Sumber Daya Tambahan:

Integrasi gRPC dengan HttpClientFactory menawarkan cara terpusat untuk membuat klien gRPC. Ini dapat digunakan sebagai alternatif untuk mengonfigurasi instans klien gRPC yang berdiri sendiri. Integrasi pabrik tersedia dalam paket Grpc.Net.ClientFactory NuGet.

Pabrik menawarkan manfaat berikut:

  • Menyediakan lokasi pusat untuk mengonfigurasi instans klien gRPC logis
  • Mengelola masa pakai yang mendasarinya HttpClientMessageHandler
  • Penyebaran tenggat waktu dan pembatalan otomatis dalam layanan gRPC core ASP.NET

Mendaftarkan klien gRPC

Untuk mendaftarkan klien gRPC, metode ekstensi generik AddGrpcClient dapat digunakan dalam Startup.ConfigureServices, menentukan kelas klien jenis gRPC dan alamat layanan:

services.AddGrpcClient<Greeter.GreeterClient>(o =>
{
    o.Address = new Uri("https://localhost:5001");
});

Jenis klien gRPC terdaftar sebagai sementara dengan injeksi dependensi (DI). Klien sekarang dapat disuntikkan dan dikonsumsi langsung dalam jenis yang dibuat oleh DI. ASP.NET pengontrol Core MVC, hub, SignalR dan layanan gRPC adalah tempat di mana klien gRPC dapat secara otomatis disuntikkan:

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

Mengonfigurasi HttpHandler

HttpClientFactory membuat yang HttpMessageHandler digunakan oleh klien gRPC. Metode standar HttpClientFactory dapat digunakan untuk menambahkan middleware permintaan keluar atau untuk mengonfigurasi dasar HttpClientHandlerHttpClientdari :

services
    .AddGrpcClient<Greeter.GreeterClient>(o =>
    {
        o.Address = new Uri("https://localhost:5001");
    })
    .ConfigurePrimaryHttpMessageHandler(() =>
    {
        var handler = new HttpClientHandler();
        handler.ClientCertificates.Add(LoadCertificate());
        return handler;
    });

Untuk informasi selengkapnya, lihat Membuat permintaan HTTP menggunakan IHttpClientFactory.

Mengonfigurasi Interceptors

Pencegat gRPC dapat ditambahkan ke klien menggunakan metode .AddInterceptor

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

Kode sebelumnya:

  • Mendaftarkan jenis.GreeterClient
  • LoggingInterceptor Mengonfigurasi untuk klien ini. LoggingInterceptor dibuat sekali dan dibagikan antar GreeterClient instans.

Secara default, pencegat dibuat sekali dan dibagikan antar klien. Perilaku ini dapat ditimpa dengan menentukan cakupan saat mendaftarkan pencegat. Pabrik klien dapat dikonfigurasi untuk membuat pencegat baru untuk setiap klien dengan menentukan InterceptorScope.Client.

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

Membuat pencegat cakupan klien berguna ketika pencegat memerlukan layanan cakupan atau sementara dari DI.

Pencegat gRPC atau kredensial saluran dapat digunakan untuk mengirim Authorization metadata dengan setiap permintaan. Untuk informasi selengkapnya tentang mengonfigurasi autentikasi, lihat Mengirim token pembawa dengan pabrik klien gRPC.

Mengonfigurasi Saluran

Konfigurasi tambahan dapat diterapkan ke saluran menggunakan ConfigureChannel metode :

services
    .AddGrpcClient<Greeter.GreeterClient>(o =>
    {
        o.Address = new Uri("https://localhost:5001");
    })
    .ConfigureChannel(o =>
    {
        o.Credentials = new CustomCredentials();
    });

ConfigureChannel diteruskan instans GrpcChannelOptions . Untuk informasi selengkapnya, lihat mengonfigurasi opsi klien.

Catatan

Beberapa properti diatur pada GrpcChannelOptions sebelum ConfigureChannel panggilan balik dijalankan:

Nilai-nilai ini dapat ditimpa oleh ConfigureChannel.

Tenggat waktu dan penyebaran pembatalan

Klien gRPC yang dibuat oleh pabrik dalam layanan gRPC dapat dikonfigurasi dengan EnableCallContextPropagation() untuk secara otomatis menyebarluaskan tenggat waktu dan token pembatalan ke panggilan anak. Metode EnableCallContextPropagation() ekstensi tersedia dalam paket NuGet Grpc.AspNetCore.Server.ClientFactory .

Propagasi konteks panggilan berfungsi dengan membaca tenggat waktu dan token pembatalan dari konteks permintaan gRPC saat ini dan secara otomatis menyebarkannya ke panggilan keluar yang dilakukan oleh klien gRPC. Penyebaran konteks panggilan adalah cara yang sangat baik untuk memastikan bahwa skenario gRPC yang kompleks dan berlapis selalu menyebarluaskan tenggat waktu dan pembatalan.

services
    .AddGrpcClient<Greeter.GreeterClient>(o =>
    {
        o.Address = new Uri("https://localhost:5001");
    })
    .EnableCallContextPropagation();

Secara default, EnableCallContextPropagation menimbulkan kesalahan jika klien digunakan di luar konteks panggilan gRPC. Kesalahan dirancang untuk memberi tahu Anda bahwa tidak ada konteks panggilan untuk disebarluaskan. Jika Anda ingin menggunakan klien di luar konteks panggilan, tekan kesalahan saat klien dikonfigurasi dengan SuppressContextNotFoundErrors:

services
    .AddGrpcClient<Greeter.GreeterClient>(o =>
    {
        o.Address = new Uri("https://localhost:5001");
    })
    .EnableCallContextPropagation(o => o.SuppressContextNotFoundErrors = true);

Untuk informasi selengkapnya tentang tenggat waktu dan pembatalan RPC, lihat Layanan gRPC andal dengan tenggat waktu dan pembatalan.

Klien bernama

Biasanya, jenis klien gRPC didaftarkan sekali dan kemudian disuntikkan langsung ke konstruktor jenis oleh DI. Namun, ada skenario di mana berguna untuk memiliki beberapa konfigurasi untuk satu klien. Misalnya, klien yang melakukan panggilan gRPC dengan dan tanpa autentikasi.

Beberapa klien dengan jenis yang sama dapat didaftarkan dengan memberi nama kepada setiap klien. Setiap klien bernama dapat memiliki konfigurasinya sendiri. Metode ekstensi generik AddGrpcClient memiliki kelebihan beban yang menyertakan parameter nama:

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

Kode sebelumnya:

  • Mendaftarkan GreeterClient jenis dua kali, menentukan nama unik untuk masing-masing.
  • Mengonfigurasi pengaturan yang berbeda untuk setiap klien bernama. Pendaftaran GreeterAuthenticated menambahkan kredensial ke saluran sehingga panggilan gRPC yang dilakukan dengannya diautentikasi.

Klien gRPC bernama dibuat dalam kode aplikasi menggunakan GrpcClientFactory. Jenis dan nama klien yang diinginkan ditentukan menggunakan metode generik GrpcClientFactory.CreateClient :

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

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

Sumber Daya Tambahan: