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 daricontinuation
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. Gunakancontext
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 menggunakanHandleResponse
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 mengembalikanCallInvoker
. 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:
ClientLoggerInterceptor
ClientMonitoringInterceptor
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 opsiInterceptors
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 menggunakanServerCallContext
parameter denganServerCallContext.GetHttpContext
metode ekstensi. Fitur ini khusus untuk pencegat yang berjalan di ASP.NET Core.
- Di middleware,
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.
- Beroperasi pada lapisan abstraksi gRPC menggunakan
- 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:
ASP.NET Core