C# Academy · Lección

Plazos, cancelación e interceptores

Aplique tiempos de espera mediante deadlines, propague CancellationToken y añada aspectos transversales mediante interceptores de gRPC.

Lección 4 de 412 pasos

Plazos, cancelación e interceptores es una lección gratuita de C# Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C# Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C# Academy incluye 4 lecciones en total.

Fiabilidad en gRPC: plazos y cancelación

Los servicios gRPC en producción deben gestionar dos aspectos críticos de fiabilidad: los plazos (cuánto tiempo esperará el cliente) y la cancelación (detener el trabajo antes de tiempo). Juntos evitan el agotamiento de recursos y los fallos en cascada.

Establecer un plazo para una llamada

Un plazo es un momento absoluto antes del cual debe completarse la llamada. Establézcalo con CallOptions. Si se supera, el servidor recibe una cancelación y el cliente obtiene 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);

Gestionar DeadlineExceeded en el cliente

Capture RpcException y compruebe el código de estado para diferenciar la expiración del plazo de otros errores.

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

Respetar los plazos en el servidor

El servidor debe comprobar context.CancellationToken durante las operaciones largas. Cuando vence el plazo, este token se cancela automáticamente.

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

Propagación de CancellationToken

Propague siempre el token de cancelación del servidor por toda la cadena de llamadas asíncronas. Si lo ignora, las llamadas canceladas continuarán consumiendo recursos innecesariamente.

// 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

Interceptores de gRPC: concepto

Los interceptores son el equivalente en gRPC del middleware de ASP.NET Core: se ejecutan antes o después de las llamadas RPC y pueden inspeccionar o modificar solicitudes, respuestas y excepciones. Son ideales para el registro, la autenticación y la lógica de reintentos.

Crear un interceptor del servidor

Herede de Interceptor y sobrescriba el tipo de método que desea interceptar. Llame a continuation para continuar con el controlador real.

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

Registrar interceptores del servidor

Registre los interceptores globalmente (para todos los servicios) o por servicio en Program.cs. El contenedor de DI resuelve las dependencias del constructor.

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

Interceptores del cliente

Los interceptores del cliente envuelven las llamadas salientes; resultan útiles para añadir encabezados de autenticación, lógica de reintentos o ID de correlación sin modificar cada punto de llamada.

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 de excepciones

Un interceptor de excepciones del servidor convierte las excepciones no controladas en RpcExceptions, evitando que se filtren detalles internos a los clientes.

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

Comprobación rápida

¿Qué ocurre cuando una llamada gRPC supera su plazo?

Resumen: plazos, cancelación e interceptores

Ideas clave:

  • Establezca siempre plazos en las llamadas del cliente para evitar esperas ilimitadas
  • Compruebe context.CancellationToken en el servidor y páselo a todas las llamadas asíncronas
  • Los interceptores gestionan aspectos transversales (registro, autenticación y mapeo de errores) sin sobrecargar el código del servicio
  • Interceptores del servidor: sobrescriba los métodos de controladores Unary/Stream y llame a continuation
  • Interceptores del cliente: conéctelos a la cadena de invocadores del canal
Gratis para empezar

Aprende C# con un tutor de IA — gratis

Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.

Cursos
93
Lecciones
346

Preguntas frecuentes

¿La lección «Plazos, cancelación e interceptores» es gratis?

Sí — el texto completo de «Plazos, cancelación e interceptores» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C# Academy, actualiza a CoddyKit PRO. El curso de C# Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Plazos, cancelación e interceptores»?

Aplique tiempos de espera mediante deadlines, propague CancellationToken y añada aspectos transversales mediante interceptores de gRPC. Practicas C# Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar C# Academy?

No se requiere experiencia previa. C# Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «Plazos, cancelación e interceptores»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de C# Academy?

Sí. Cada lección de C# Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Fundamentos de gRPC y Protobuf
  2. RPC unarios y streaming del servidor
  3. Streaming del cliente y bidireccional
  4. Plazos, cancelación e interceptores
← Volver a C# Academy