C# Academy · Lekcja

Limity czasu, anulowanie i interceptory

Stosuj limity czasu za pomocą deadline’ów, propaguj CancellationToken i dodawaj przekrojowe aspekty za pomocą interceptorów gRPC.

Lekcja 4 z 412 kroki

Limity czasu, anulowanie i interceptory to bezpłatna lekcja C# Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C# Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C# Academy zawiera 4 lekcji w sumie.

Niezawodność w gRPC: limity czasu i anulowanie

Usługi gRPC działające produkcyjnie muszą obsługiwać dwa kluczowe aspekty niezawodności: limity czasu (jak długo klient będzie czekać) oraz anulowanie (zatrzymywanie pracy przed jej ukończeniem). Razem zapobiegają wyczerpaniu zasobów i awariom kaskadowym.

Ustawianie limitu czasu wywołania

Limit czasu to określony moment, do którego wywołanie musi się zakończyć. Ustawia się go za pomocą CallOptions. Po jego przekroczeniu serwer otrzymuje sygnał anulowania, a klient otrzymuje StatusCode.DeadlineExceeded.

var deadline = DateTime.UtcNow.AddSeconds(5);

var reply = await client.GetOrderAsync(
    new GetOrderRequest { Id = 42 },
    deadline: deadline);

// Or via CallOptions:
var options = new CallOptions(deadline: deadline);
var reply2 = await client.GetOrderAsync(
    new GetOrderRequest { Id = 42 }, options);

Obsługa DeadlineExceeded po stronie klienta

Przechwyć RpcException i sprawdź kod stanu, aby odróżnić wygaśnięcie limitu czasu od innych błędów.

try
{
    var reply = await client.GetOrderAsync(
        new GetOrderRequest { Id = 42 },
        deadline: DateTime.UtcNow.AddSeconds(3));
}
catch (RpcException ex) when (ex.StatusCode == StatusCode.DeadlineExceeded)
{
    Console.WriteLine("Call timed out");
}
catch (RpcException ex)
{
    Console.WriteLine($"gRPC error: {ex.Status.Detail}");
}

Przestrzeganie limitów czasu po stronie serwera

Serwer powinien sprawdzać context.CancellationToken podczas długotrwałych operacji. Po upływie limitu ten token jest automatycznie anulowany.

public override async Task<ReportResponse> GenerateReport(
    ReportRequest request,
    ServerCallContext context)
{
    var ct = context.CancellationToken;

    // Pass ct to every async call — work stops when deadline hits
    var data = await _db.FetchLargeDatasetAsync(request.Filters, ct);
    var report = await _reportEngine.BuildAsync(data, ct);

    ct.ThrowIfCancellationRequested(); // explicit check before CPU work
    return MapToResponse(report);
}

Propagowanie CancellationToken

Zawsze propaguj CancellationToken serwera w całym łańcuchu wywołań asynchronicznych. Jeśli go zignorujesz, anulowane wywołania będą nadal niepotrzebnie zużywać zasoby.

// GOOD: token flows through the call chain
await _db.Products.AsNoTracking()
    .Where(p => p.IsActive)
    .ToListAsync(context.CancellationToken); // cancels if client disconnects

// BAD: ignores cancellation
await _db.Products.ToListAsync(); // keeps running after deadline

Interceptory gRPC: koncepcja

Interceptory są odpowiednikiem middleware ASP.NET Core w gRPC — uruchamiają się przed wywołaniami RPC i po nich, a także mogą analizować lub modyfikować żądania, odpowiedzi i wyjątki. Doskonale nadają się do logowania, uwierzytelniania i logiki ponawiania prób.

Tworzenie interceptora po stronie serwera

Dziedzicz po Interceptor i przesłoń typ metody, który chcesz przechwytywać. Wywołaj continuation, aby przejść do właściwego handlera.

using Grpc.Core.Interceptors;

public class LoggingInterceptor : Interceptor
{
    private readonly ILogger<LoggingInterceptor> _logger;
    public LoggingInterceptor(ILogger<LoggingInterceptor> l) => _logger = l;

    public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
        TRequest request,
        ServerCallContext context,
        UnaryServerMethod<TRequest, TResponse> continuation)
    {
        _logger.LogInformation("gRPC call: {Method}", context.Method);
        var sw = System.Diagnostics.Stopwatch.StartNew();
        var response = await continuation(request, context);
        _logger.LogInformation("Completed in {Ms}ms", sw.ElapsedMilliseconds);
        return response;
    }
}

Rejestrowanie interceptorów serwera

Rejestruj interceptory globalnie (dla wszystkich usług) lub dla konkretnej usługi w Program.cs. Kontener DI rozwiązuje zależności konstruktora.

// Globally for all gRPC services:
builder.Services.AddGrpc(opt =>
    opt.Interceptors.Add<LoggingInterceptor>());

// Or per service:
builder.Services.AddGrpc();
builder.Services.AddSingleton<LoggingInterceptor>();

app.MapGrpcService<OrderService>()
   .AddInterceptor<LoggingInterceptor>();

Interceptory po stronie klienta

Interceptory klienta opakowują wychodzące wywołania — przydają się do dodawania nagłówków uwierzytelniania, logiki ponawiania prób lub identyfikatorów korelacji bez modyfikowania każdego miejsca wywołania.

public class AuthInterceptor : Interceptor
{
    private readonly ITokenProvider _tokens;
    public AuthInterceptor(ITokenProvider t) => _tokens = t;

    public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(
        TRequest request,
        ClientInterceptorContext<TRequest, TResponse> context,
        AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
    {
        var headers = context.Options.Headers ?? new Metadata();
        headers.Add("authorization", $"Bearer {_tokens.GetToken()}");
        var newContext = new ClientInterceptorContext<TRequest, TResponse>(
            context.Method, context.Host,
            context.Options.WithHeaders(headers));
        return continuation(request, newContext);
    }
}

// Attach to channel:
var invoker = channel.Intercept(new AuthInterceptor(tokenProvider));
var client = new OrderService.OrderServiceClient(invoker);

Interceptor wyjątków

Serwerowy interceptor wyjątków przekształca nieobsłużone wyjątki w RpcExceptions, zapobiegając ujawnieniu klientom szczegółów wewnętrznych.

public class ExceptionInterceptor : Interceptor
{
    public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
        TRequest request,
        ServerCallContext context,
        UnaryServerMethod<TRequest, TResponse> continuation)
    {
        try
        {
            return await continuation(request, context);
        }
        catch (NotFoundException ex)
        {
            throw new RpcException(new Status(StatusCode.NotFound, ex.Message));
        }
        catch (Exception ex)
        {
            throw new RpcException(new Status(StatusCode.Internal, "Internal error"));
        }
    }
}

Szybkie sprawdzenie

Co się dzieje, gdy wywołanie gRPC przekroczy limit czasu?

Podsumowanie: limity czasu, anulowanie i interceptory

Najważniejsze informacje:

  • Zawsze ustawiaj limity czasu dla wywołań klienta, aby zapobiegać nieograniczonemu oczekiwaniu
  • Sprawdzaj context.CancellationToken na serwerze i przekazuj go do wszystkich wywołań asynchronicznych
  • Interceptory obsługują przekrojowe aspekty (logowanie, uwierzytelnianie, mapowanie błędów) bez zaśmiecania kodu usługi
  • Interceptory serwera: przesłaniaj metody obsługi Unary/Stream i wywołuj continuation
  • Interceptory klienta: dołączaj do łańcucha wywołującego kanału
Bezpłatny start

Ucz się C# dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
93
Lekcje
346

Często zadawane pytania

Czy lekcja „Limity czasu, anulowanie i interceptory” jest bezpłatna?

Tak — pełny tekst „Limity czasu, anulowanie i interceptory” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C# Academy, przejdź na CoddyKit PRO. Kurs C# Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Limity czasu, anulowanie i interceptory”?

Stosuj limity czasu za pomocą deadline’ów, propaguj CancellationToken i dodawaj przekrojowe aspekty za pomocą interceptorów gRPC. Ćwiczysz C# Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć C# Academy?

Nie wymagamy żadnego doświadczenia. C# Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Limity czasu, anulowanie i interceptory”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji C# Academy?

Tak. Każda lekcja C# Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Podstawy gRPC i Protobuf
  2. Jednoargumentowe i strumieniowane RPC po stronie serwera
  3. Strumieniowanie klienta i dwukierunkowe
  4. Limity czasu, anulowanie i interceptory
← Powrót do C# Academy