przechwytywanie gRPC na platformie .NET
Uwaga
Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu platformy .NET 9.
Ważne
Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu platformy .NET 9.
Przez Ernest Nguyen
Przechwytywanie to koncepcja gRPC, która umożliwia aplikacjom interakcję z przychodzącymi lub wychodzącymi wywołaniami gRPC. Oferują one sposób wzbogacania potoku przetwarzania żądań.
Przechwytniki są konfigurowane dla kanału lub usługi i wykonywane automatycznie dla każdego wywołania gRPC. Ponieważ przechwytywanie jest niewidoczne dla logiki aplikacji użytkownika, jest doskonałym rozwiązaniem dla typowych przypadków, takich jak rejestrowanie, monitorowanie, uwierzytelnianie i walidacja.
Typ: Interceptor
Przechwytywanie można zaimplementować zarówno dla serwerów gRPC, jak i klientów, tworząc klasę dziedziczą po typie Interceptor
:
public class ExampleInterceptor : Interceptor
{
}
Domyślnie klasa bazowa Interceptor
nic nie robi. Dodaj zachowanie do przechwytywania, przesłaniając odpowiednie metody klasy bazowej w implementacji przechwytywania.
Przechwytniki klienta
przechwytujące przechwytniki klienta gRPC przechwytujące wychodzące wywołania RPC. Zapewniają one dostęp do wysłanego żądania, odpowiedzi przychodzącej i kontekstu wywołania po stronie klienta.
Interceptor
metody zastąpienia dla klienta:
BlockingUnaryCall
: przechwytuje blokowanie wywołania jednoargumentowego wywołania RPC.AsyncUnaryCall
: przechwytuje asynchroniczne wywołanie jednoargumentowego wywołania RPC.AsyncClientStreamingCall
: przechwytuje asynchroniczne wywołanie wywołania RPC przesyłania strumieniowego klienta.AsyncServerStreamingCall
: przechwytuje asynchroniczne wywołanie wywołania RPC przesyłania strumieniowego serwera.AsyncDuplexStreamingCall
: przechwytuje asynchroniczne wywołanie dwukierunkowego przesyłania strumieniowego RPC.
Ostrzeżenie
Mimo że obie BlockingUnaryCall
metody i AsyncUnaryCall
odwołują się do jednoargumentowych kontrolerów RPC, nie są one wymienne. Wywołanie blokujące nie jest przechwytywane przez AsyncUnaryCall
element , a wywołanie asynchroniczne nie jest przechwytywane przez BlockingUnaryCall
element .
Tworzenie przechwytywania gRPC klienta
Poniższy kod przedstawia podstawowy przykład przechwytywania asynchronicznego wywołania jednoargumentowego:
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);
}
}
Zastępowanie AsyncUnaryCall
:
- Przechwytuje asynchroniczne jednoargumentowe wywołanie.
- Rejestruje szczegółowe informacje o wywołaniu.
continuation
Wywołuje parametr przekazany do metody . Spowoduje to wywołanie następnego przechwytywania w łańcuchu lub wywołania bazowego, jeśli jest to ostatni przechwytnik.
Metody dla Interceptor
każdego rodzaju metody usługi mają różne sygnatury. Jednak koncepcja i continuation
context
parametry pozostają takie same:
continuation
jest delegatem, który wywołuje następny przechwytnik w łańcuchu lub źródłowy wywołanie wywołania (jeśli w łańcuchu nie ma przechwytywania). Nie jest to błąd, aby wywołać go zero lub wiele razy. Przechwytywanie nie jest wymagane do zwrócenia reprezentacji wywołania (AsyncUnaryCall
w przypadku jednoargumentowego wywołania RPC) zwróconego z delegatacontinuation
. Pominięcie wywołania delegata i zwrócenie własnego wystąpienia reprezentacji wywołania powoduje przerwanie łańcucha przechwytujących i natychmiastowe zwrócenie skojarzonej odpowiedzi.context
program przenosi wartości o określonym zakresie skojarzone z wywołaniem po stronie klienta. Służycontext
do przekazywania metadanych, takich jak podmioty zabezpieczeń, poświadczenia lub dane śledzenia. Ponadto prowadzicontext
informacje o terminach ostatecznych i anulowaniu. Aby uzyskać więcej informacji, zobacz Reliable gRPC services with deadline and cancellation (Niezawodne usługi gRPC z terminami i anulowaniem).
Oczekiwanie na odpowiedź w przechwytywaniu klienta
Przechwytywanie może oczekiwać na odpowiedź w wywołaniach jednoargumentowych i przesyłania strumieniowego klienta przez zaktualizowanie AsyncUnaryCall<TResponse>.ResponseAsync
wartości lub 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);
}
}
}
Powyższy kod ma następujące działanie:
- Tworzy nowy przechwytujący, który zastępuje
AsyncUnaryCall
element . - Zastępowanie
AsyncUnaryCall
:- Wywołuje parametr ,
continuation
aby wywołać następny element w łańcuchu przechwytywania. - Tworzy nowe
AsyncUnaryCall<TResponse>
wystąpienie na podstawie wyniku kontynuacji. - Opakowuje
ResponseAsync
zadanie przy użyciuHandleResponse
metody . - Oczekuje na odpowiedź za pomocą polecenia
HandleResponse
. Oczekiwanie na odpowiedź umożliwia dodanie logiki po otrzymaniu odpowiedzi przez klienta. Oczekując na odpowiedź w bloku try-catch, można rejestrować błędy z wywołań.
- Wywołuje parametr ,
Aby uzyskać więcej informacji na temat tworzenia przechwytywania klienta, zobacz ClientLoggerInterceptor.cs
przykład w grpc/grpc-dotnet
repozytorium GitHub.
Konfigurowanie przechwytywania klientów
Przechwytywanie klientów gRPC jest konfigurowane w kanale.
Następujący kod powoduje:
- Tworzy kanał przy użyciu polecenia
GrpcChannel.ForAddress
. Intercept
Używa metody rozszerzenia do skonfigurowania kanału do używania przechwytywania. Należy pamiętać, że ta metoda zwraca wartośćCallInvoker
. Silnie typizowanych klientów gRPC można tworzyć na podstawie wywołania, podobnie jak kanał.- Tworzy klienta z wywołania. Wywołania gRPC wykonywane przez klienta automatycznie wykonują przechwytywanie.
using var channel = GrpcChannel.ForAddress("https://localhost:5001");
var invoker = channel.Intercept(new ClientLoggerInterceptor());
var client = new Greeter.GreeterClient(invoker);
Intercept
Metodę rozszerzenia można połączyć w łańcuch, aby skonfigurować wiele przechwytujących dla kanału. Alternatywnie istnieje Intercept
przeciążenie, które akceptuje wiele przechwytujących. W przypadku pojedynczego wywołania gRPC można wykonać dowolną liczbę przechwytywania, jak pokazano w poniższym przykładzie:
var invoker = channel
.Intercept(new ClientTokenInterceptor())
.Intercept(new ClientMonitoringInterceptor())
.Intercept(new ClientLoggerInterceptor());
Przechwytniki są wywoływane w odwrotnej kolejności metod rozszerzeń łańcuchowych Intercept
. W poprzednim kodzie przechwytujące są wywoływane w następującej kolejności:
ClientLoggerInterceptor
ClientMonitoringInterceptor
ClientTokenInterceptor
Aby uzyskać informacje na temat konfigurowania przechwytywania za pomocą fabryki klienta gRPC, zobacz integracja fabryki klienta gRPC na platformie .NET.
Przechwytniki serwera
przechwytatory serwera gRPC przechwytywać przychodzące żądania RPC. Zapewniają one dostęp do żądania przychodzącego, odpowiedzi wychodzącej i kontekstu wywołania po stronie serwera.
Interceptor
metody przesłaniania dla serwera:
UnaryServerHandler
: przechwytuje jednoargumentowy RPC.ClientStreamingServerHandler
: przechwytuje RPC przesyłania strumieniowego klienta.ServerStreamingServerHandler
: przechwytuje RPC przesyłania strumieniowego serwera.DuplexStreamingServerHandler
: przechwytuje dwukierunkowe przesyłanie strumieniowe RPC.
Tworzenie przechwytywania gRPC serwera
Poniższy kod przedstawia przykład przechwycenia przychodzącego jednoargumentowego RPC:
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;
}
}
}
Zastępowanie UnaryServerHandler
:
- Przechwytuje przychodzące jednoargumentowe wywołanie.
- Rejestruje szczegółowe informacje o wywołaniu.
continuation
Wywołuje parametr przekazany do metody . Spowoduje to wywołanie następnego przechwytnika w łańcuchu lub procedurę obsługi usługi, jeśli jest to ostatni przechwytujący.- Rejestruje wszelkie wyjątki. Oczekiwanie na kontynuację umożliwia dodanie logiki po wykonaniu metody usługi. Oczekując na kontynuację w bloku try-catch, błędy z metod można rejestrować.
Podpis metod przechwytywania klienta i serwera jest podobny:
continuation
oznacza delegata dla przychodzącego RPC wywołującego następny przechwytywanie w łańcuchu lub program obsługi usługi (jeśli w łańcuchu nie ma przechwytnika). Podobnie jak w przypadku przechwytywania klienta, można go wywołać w dowolnym momencie i nie ma potrzeby zwracania odpowiedzi bezpośrednio z delegata kontynuacji. Logikę ruchu wychodzącego można dodać po wykonaniu programu obsługi usługi przez oczekiwanie na kontynuację.context
przenosi metadane skojarzone z wywołaniem po stronie serwera, takie jak metadane żądania, terminy i anulowanie lub wynik wywołania procedury RPC.
Aby uzyskać więcej informacji na temat tworzenia przechwytywania serwera, zobacz ServerLoggerInterceptor.cs
przykład w grpc/grpc-dotnet
repozytorium GitHub.
Konfigurowanie przechwytywania serwerów
Przechwytniki serwera gRPC są konfigurowane podczas uruchamiania. Następujący kod powoduje:
- Dodaje gRPC do aplikacji za pomocą polecenia
AddGrpc
. - Konfiguruje
ServerLoggerInterceptor
wszystkie usługi przez dodanie jej do kolekcjiInterceptors
opcji usługi.
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc(options =>
{
options.Interceptors.Add<ServerLoggerInterceptor>();
});
}
Przechwytnika można również skonfigurować dla określonej usługi przy użyciu i AddServiceOptions
określić typ usługi.
public void ConfigureServices(IServiceCollection services)
{
services
.AddGrpc()
.AddServiceOptions<GreeterService>(options =>
{
options.Interceptors.Add<ServerLoggerInterceptor>();
});
}
Przechwytniki są uruchamiane w kolejności, w której są dodawane do elementu InterceptorCollection
. Jeśli zarówno globalne, jak i pojedyncze przechwytniki usługi są skonfigurowane, to globalnie skonfigurowane przechwytniki są uruchamiane przed tymi skonfigurowanymi dla pojedynczej usługi.
Domyślnie przechwytywanie serwerów gRPC ma okres istnienia poszczególnych żądań. Zastąpienie tego zachowania jest możliwe poprzez zarejestrowanie typu przechwytywania za pomocą iniekcji zależności. Poniższy przykład rejestruje element ServerLoggerInterceptor
z pojedynczym okresem istnienia:
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc(options =>
{
options.Interceptors.Add<ServerLoggerInterceptor>();
});
services.AddSingleton<ServerLoggerInterceptor>();
}
Przechwytywanie gRPC a oprogramowanie pośredniczące
oprogramowanie pośredniczące ASP.NET Core oferuje podobne funkcje w porównaniu do przechwytywania w aplikacjach gRPC opartych na rdzeniach C. ASP.NET Core oprogramowania pośredniczącego i przechwytywania są koncepcyjnie podobne. Oba:
- Są używane do konstruowania potoku obsługującego żądanie gRPC.
- Zezwalaj na wykonywanie pracy przed lub po następnym składniku w potoku.
- Zapewnianie dostępu do usługi
HttpContext
:- W przypadku oprogramowania pośredniczącego parametr
HttpContext
jest parametrem . - W przechwytywaniu
HttpContext
można uzyskać dostęp przy użyciu parametruServerCallContext
ServerCallContext.GetHttpContext
z metodą rozszerzenia. Ta funkcja jest specyficzna dla przechwytywania uruchomionych w ASP.NET Core.
- W przypadku oprogramowania pośredniczącego parametr
gRPC Interceptor różnice w ASP.NET Core Middleware:
- Avicode:
- Działanie na warstwie gRPC abstrakcji przy użyciu klasy
ServerCallContext
. - Zapewnianie dostępu do:
- Zdeserializowany komunikat wysłany do wywołania.
- Komunikat zwrócony z wywołania przed jego serializacji.
- Może przechwytywać wyjątki zgłaszane przez usługi gRPC i obsługiwać je.
- Działanie na warstwie gRPC abstrakcji przy użyciu klasy
- Oprogramowanie pośredniczące:
- Uruchamia wszystkie żądania HTTP.
- Działa przed przechwytywaniem gRPC.
- Działa na podstawowych komunikatach HTTP/2.
- Może uzyskiwać dostęp tylko do bajtów ze strumieni żądania i odpowiedzi.