Bagikan melalui


penyadap gRPC pada .NET

Catatan

Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.

Peringatan

Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.

Penting

Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.

Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.

Oleh Ernest Nguyen

Pencegat adalah konsep gRPC yang memungkinkan aplikasi berinteraksi dengan panggilan gRPC masuk atau keluar. Mereka menawarkan cara untuk memperkaya alur pemrosesan permintaan.

Pencegat dikonfigurasi untuk saluran atau layanan dan dijalankan secara otomatis untuk setiap panggilan gRPC. Karena pencegat transparan terhadap logika aplikasi pengguna, mereka adalah solusi yang sangat baik untuk kasus umum, seperti pengelogan, pemantauan, autentikasi, dan validasi.

Interceptor type

Pencegat dapat diimplementasikan untuk server gRPC dan klien dengan membuat kelas yang mewarisi dari Interceptor jenis :

public class ExampleInterceptor : Interceptor
{
}

Secara default, Interceptor kelas dasar tidak melakukan apa pun. Tambahkan perilaku ke pencegat dengan mengambil alih metode kelas dasar yang sesuai dalam implementasi pencegat.

Pencegat klien

pencegat klien gRPC mencegat pemanggilan RPC keluar. Mereka menyediakan akses ke permintaan terkirim, respons masuk, dan konteks untuk panggilan sisi klien.

Interceptor metode untuk mengambil alih klien:

  • BlockingUnaryCall: Mencegat pemanggilan pemblokiran RPC unary.
  • AsyncUnaryCall: Mencegat pemanggilan ASINKRON dari RPC tidak sinkron.
  • AsyncClientStreamingCall: Mencegat pemanggilan asinkron RPC streaming klien.
  • AsyncServerStreamingCall: Mencegat pemanggilan asinkron RPC streaming server.
  • AsyncDuplexStreamingCall: Mencegat pemanggilan asinkron RPC streaming dua arah.

Peringatan

Meskipun keduanya BlockingUnaryCall dan AsyncUnaryCall merujuk ke RPC tidak biasa, mereka tidak dapat dipertukarkan. Pemanggilan pemblokiran tidak dicegat oleh AsyncUnaryCall, dan pemanggilan asinkron tidak disadap oleh BlockingUnaryCall.

Membuat pencegat gRPC klien

Kode berikut menyajikan contoh dasar mencegat pemanggilan asinkron dari panggilan tidak sinkron:

public class ClientLoggingInterceptor : Interceptor
{
    private readonly ILogger _logger;

    public ClientLoggingInterceptor(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger<ClientLoggingInterceptor>();
    }

    public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(
        TRequest request,
        ClientInterceptorContext<TRequest, TResponse> context,
        AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
    {
        _logger.LogInformation("Starting call. Type/Method: {Type} / {Method}",
            context.Method.Type, context.Method.Name);
        return continuation(request, context);
    }
}

Penimpaan AsyncUnaryCall:

  • Mencegat panggilan tidak sinkron.
  • Mencatat detail tentang panggilan.
  • Memanggil parameter yang continuation diteruskan ke metode . Ini memanggil pencegat berikutnya dalam rantai atau pemanggil panggilan yang mendasarinya jika ini adalah pencegat terakhir.

Metode pada Interceptor untuk setiap jenis metode layanan memiliki tanda tangan yang berbeda. Namun, konsep di belakang continuation dan context parameter tetap sama:

  • continuation adalah delegasi yang memanggil pencegat berikutnya dalam rantai atau pemanggil panggilan yang mendasarinya (jika tidak ada pencegat yang tersisa dalam rantai). Ini bukan kesalahan untuk menyebutnya nol atau beberapa kali. Pencegat tidak diperlukan untuk mengembalikan representasi panggilan (AsyncUnaryCall dalam kasus RPC unary) yang dikembalikan dari continuation delegasi. Menghilangkan panggilan delegasi dan mengembalikan instans representasi panggilan Anda sendiri akan memutus rantai pencegat dan segera mengembalikan respons terkait.
  • context membawa nilai cakupan yang terkait dengan panggilan sisi klien. Gunakan context untuk meneruskan metadata, seperti prinsip keamanan, kredensial, atau data pelacakan. Selain itu, context membawa informasi tentang tenggat waktu dan pembatalan. Untuk informasi selengkapnya, lihat Layanan gRPC andal dengan tenggat waktu dan pembatalan.

Menunggu respons dalam pencegat klien

Pencegat dapat menunggu respons dalam panggilan streaming unary dan klien dengan memperbarui AsyncUnaryCall<TResponse>.ResponseAsync nilai atau AsyncClientStreamingCall<TRequest, TResponse>.ResponseAsync .

public class ErrorHandlerInterceptor : Interceptor
{
    public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(
        TRequest request,
        ClientInterceptorContext<TRequest, TResponse> context,
        AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
    {
        var call = continuation(request, context);

        return new AsyncUnaryCall<TResponse>(
            HandleResponse(call.ResponseAsync),
            call.ResponseHeadersAsync,
            call.GetStatus,
            call.GetTrailers,
            call.Dispose);
    }

    private async Task<TResponse> HandleResponse<TResponse>(Task<TResponse> inner)
    {
        try
        {
            return await inner;
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException("Custom error", ex);
        }
    }
}

Kode sebelumnya:

  • Membuat pencegat baru yang mengambil alih AsyncUnaryCall.
  • Penimpaan AsyncUnaryCall:
    • continuation Memanggil parameter untuk memanggil item berikutnya dalam rantai pencegat.
    • Membuat instans baru AsyncUnaryCall<TResponse> berdasarkan hasil kelanjutan.
    • Membungkus ResponseAsync tugas menggunakan HandleResponse metode .
    • Menunggu respons dengan HandleResponse. Menunggu respons memungkinkan logika ditambahkan setelah klien menerima respons. Dengan menunggu respons dalam blok try-catch, kesalahan dari panggilan dapat dicatat.

Untuk informasi selengkapnya tentang cara membuat pencegat klien, lihat ClientLoggerInterceptor.cs contoh di grpc/grpc-dotnet repositori GitHub.

Mengonfigurasi pencegat klien

Pencegat klien gRPC dikonfigurasi pada saluran.

Kode berikut:

  • Membuat saluran dengan menggunakan GrpcChannel.ForAddress.
  • Intercept Menggunakan metode ekstensi untuk mengonfigurasi saluran untuk menggunakan pencegat. Perhatikan bahwa metode ini mengembalikan CallInvoker. Klien gRPC yang sangat ditik dapat dibuat dari pemanggil seperti saluran.
  • Membuat klien dari pemanggil. Panggilan gRPC yang dilakukan oleh klien secara otomatis menjalankan pencegat.
using var channel = GrpcChannel.ForAddress("https://localhost:5001");
var invoker = channel.Intercept(new ClientLoggerInterceptor());

var client = new Greeter.GreeterClient(invoker);

Metode Intercept ekstensi dapat ditautkan untuk mengonfigurasi beberapa pencegat untuk saluran. Atau, ada Intercept kelebihan beban yang menerima beberapa pencegat. Sejumlah pencegat dapat dijalankan untuk satu panggilan gRPC, seperti yang ditunjukkan contoh berikut:

var invoker = channel
    .Intercept(new ClientTokenInterceptor())
    .Intercept(new ClientMonitoringInterceptor())
    .Intercept(new ClientLoggerInterceptor());

Pencegat dipanggil dalam urutan terbalik dari metode ekstensi berantai Intercept . Dalam kode sebelumnya, pencegat dipanggil dalam urutan berikut:

  1. ClientLoggerInterceptor
  2. ClientMonitoringInterceptor
  3. ClientTokenInterceptor

Untuk informasi tentang cara mengonfigurasi pencegat dengan pabrik klien gRPC, lihat integrasi pabrik klien gRPC di .NET.

Pencegat server

Pencegat server gRPC mencegat permintaan RPC masuk. Mereka menyediakan akses ke permintaan masuk, respons keluar, dan konteks untuk panggilan sisi server.

Interceptor metode untuk mengambil alih server:

  • UnaryServerHandler: Mencegat RPC unary.
  • ClientStreamingServerHandler: Mencegat RPC streaming klien.
  • ServerStreamingServerHandler: Mencegat RPC streaming server.
  • DuplexStreamingServerHandler: Mencegat RPC streaming dua arah.

Membuat pencegat gRPC server

Kode berikut menyajikan contoh penyadapan RPC unary yang masuk:

public class ServerLoggerInterceptor : Interceptor
{
    private readonly ILogger _logger;

    public ServerLoggerInterceptor(ILogger<ServerLoggerInterceptor> logger)
    {
        _logger = logger;
    }

    public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
        TRequest request,
        ServerCallContext context,
        UnaryServerMethod<TRequest, TResponse> continuation)
    {
        _logger.LogInformation("Starting receiving call. Type/Method: {Type} / {Method}",
            MethodType.Unary, context.Method);
        try
        {
            return await continuation(request, context);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"Error thrown by {context.Method}.");
            throw;
        }
    }
}

Penimpaan UnaryServerHandler:

  • Mencegat panggilan tidak masuk.
  • Mencatat detail tentang panggilan.
  • Memanggil parameter yang continuation diteruskan ke metode . Ini memanggil pencegat berikutnya dalam rantai atau penangan layanan jika ini adalah pencegat terakhir.
  • Mencatat pengecualian apa pun. Menunggu kelanjutan memungkinkan logika ditambahkan setelah metode layanan dijalankan. Dengan menunggu kelanjutan dalam blok try-catch, kesalahan dari metode dapat dicatat.

Tanda tangan metode pencegat klien dan server serupa:

  • continuation singkatan dari delegasi untuk RPC masuk yang memanggil pencegat berikutnya dalam rantai atau penangan layanan (jika tidak ada pencegat yang tersisa dalam rantai). Mirip dengan pencegat klien, Anda dapat memanggilnya kapan saja dan tidak perlu mengembalikan respons langsung dari delegasi kelanjutan. Logika keluar dapat ditambahkan setelah handler layanan dijalankan dengan menunggu kelanjutan.
  • context membawa metadata yang terkait dengan panggilan sisi server, seperti metadata permintaan, tenggat waktu dan pembatalan, atau hasil RPC.

Untuk informasi selengkapnya tentang cara membuat pencegat server, lihat ServerLoggerInterceptor.cs contoh di grpc/grpc-dotnet repositori GitHub.

Mengonfigurasi pencegat server

Interseptor server gRPC dikonfigurasi saat startup. Kode berikut:

  • Menambahkan gRPC ke aplikasi dengan AddGrpc.
  • ServerLoggerInterceptor Mengonfigurasi untuk semua layanan dengan menambahkannya ke koleksi opsi Interceptors layanan.
public void ConfigureServices(IServiceCollection services)
{
    services.AddGrpc(options =>
    {
        options.Interceptors.Add<ServerLoggerInterceptor>();
    });
}

Pencegat juga dapat dikonfigurasi untuk layanan tertentu dengan menggunakan AddServiceOptions dan menentukan jenis layanan.

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddGrpc()
        .AddServiceOptions<GreeterService>(options =>
        {
            options.Interceptors.Add<ServerLoggerInterceptor>();
        });
}

Pencegat dijalankan dalam urutan yang ditambahkan ke InterceptorCollection. Jika pencegat layanan global dan tunggal dikonfigurasi, maka pencegat yang dikonfigurasi secara global dijalankan sebelum yang dikonfigurasi untuk satu layanan.

Secara default, pencegat server gRPC memiliki masa pakai per permintaan. Mengambil alih perilaku ini dimungkinkan melalui mendaftarkan jenis pencegat dengan injeksi dependensi. Contoh berikut mendaftarkan ServerLoggerInterceptor dengan masa pakai singleton:

public void ConfigureServices(IServiceCollection services)
{
    services.AddGrpc(options =>
    {
        options.Interceptors.Add<ServerLoggerInterceptor>();
    });

    services.AddSingleton<ServerLoggerInterceptor>();
}

Interseptor gRPC versus Middleware

ASP.NET Core middleware menawarkan fungsionalitas serupa dibandingkan dengan pencegat di aplikasi gRPC berbasis C-core. ASP.NET Core middleware dan interceptors secara konseptual mirip. Keduanya:

  • Digunakan untuk membuat alur yang menangani permintaan gRPC.
  • Izinkan pekerjaan dilakukan sebelum atau sesudah komponen berikutnya dalam alur.
  • Berikan akses ke HttpContext:
    • Di middleware, HttpContext adalah parameter.
    • Dalam pencegat, HttpContext dapat diakses menggunakan ServerCallContext parameter dengan ServerCallContext.GetHttpContext metode ekstensi. Fitur ini khusus untuk pencegat yang berjalan di ASP.NET Core.

Perbedaan gRPC Interceptor dari ASP.NET Core Middleware:

  • Pencegat:
    • Beroperasi pada lapisan abstraksi gRPC menggunakan ServerCallContext.
    • Berikan akses ke:
      • Pesan yang dideserialisasi dikirim ke panggilan.
      • Pesan yang dikembalikan dari panggilan sebelum diserialisasikan.
    • Dapat menangkap dan menangani pengecualian yang dilemparkan dari layanan gRPC.
  • Middleware:
    • Berjalan untuk semua permintaan HTTP.
    • Berjalan sebelum pencegat gRPC.
    • Beroperasi pada pesan HTTP/2 yang mendasar.
    • Hanya dapat mengakses byte dari aliran permintaan dan respons.

Sumber Daya Tambahan: