Lección 13 de 20 · Lectura y práctica
Manejar errores y timeouts con códigos de estado gRPC
Tipo de lección: VideoConcepto claveEn sistemas distribuidos, los errores y timeouts no son excepciones sino eventos esperados. gRPC utiliza códigos de estado específicos para categorizar estos eventos, permitiendo un manejo.
Del concepto a la práctica
Taller de esta lección
Los estados gRPC deben expresar la causa operativa y guiar la reacción del cliente. Un argumento inválido no mejora con reintentos; una dependencia no disponible puede reintentarse con límite; un deadline agotado exige abandonar el trabajo asociado.
Ejemplo resuelto
sku vacío -> INVALID_ARGUMENT -> corregir entrada
inventario temporalmente caído -> UNAVAILABLE -> reintento acotado
límite de 50 ms agotado -> DEADLINE_EXCEEDED -> cancelarLa etiqueta y la acción forman una sola decisión de diseño.
En una mutación, DEADLINE_EXCEEDED no demuestra que la operación no se aplicó: la respuesta puede perderse tras el commit. Reconcilia mediante ID de operación y diseña idempotencia antes de reintentar. El trabajo de la aplicación debe cooperar con la cancelación; gRPC no mata una tarea arbitraria. Propaga a dependencias el presupuesto restante, no reinicies el plazo completo en cada salto.
Pruébalo
Simula cada causa en un servicio local.
Asigna un estado y una acción cliente por caso.
Limita los reintentos y registra el intento final.
Error frecuente: reintentar todos los errores automáticamente. Corrección: reintenta solo fallos transitorios y evita duplicar operaciones no idempotentes.
Comprueba tu resultado
Ejercicio: procesa los tres casos anteriores. Resultado esperado: cero reintentos para entrada inválida, una política limitada para disponibilidad y cancelación al superar 50 ms.

Mapa de prácticaEl control de acceso, las actualizaciones y las copias de seguridad cubren riesgos distintos. Una alerta necesita un procedimiento de respuesta para contener y recuperar el servicio. Varias capas reducen la exposición, pero ninguna garantiza seguridad absoluta.
Ver la infografía en tamaño completo ↗Tipo de lección: Video
Concepto clave
En sistemas distribuidos, los errores y timeouts no son excepciones sino eventos esperados. gRPC utiliza códigos de estado específicos para categorizar estos eventos, permitiendo un manejo estructurado que va más allá del simple "éxito/fracaso". Imagina un sistema de mensajería entre oficinas: no es lo mismo que un mensaje se pierda (DEADLINE_EXCEEDED) a que el destinatario esté ocupado (UNAVAILABLE) o que el mensaje sea ilegible (INVALID_ARGUMENT).
Los códigos de estado gRPC se dividen en cuatro categorías principales: OK (éxito), errores de cliente (4xx equivalentes), errores de servidor (5xx equivalentes) y errores de red/tiempo. La clave en producción es que cada código debe desencadenar una estrategia de recuperación específica, como retry con backoff exponencial para UNAVAILABLE, pero no para INVALID_ARGUMENT.
Cómo funciona en la práctica
Implementar un manejo robusto requiere configurar tanto el cliente como el servidor. En el servidor, debes devolver códigos específicos usando excepciones o respuestas de error. En el cliente, debes interceptar estos códigos y decidir la acción.
Ejemplo básico en Go:
// Servidor: Devolver error con código específico
status.Error(codes.DeadlineExceeded, "Timeout procesando solicitud")
// Cliente: Manejar el error
err := client.CallRPC(ctx, request)
if err != nil {
st, ok := status.FromError(err)
if ok {
switch st.Code() {
case codes.DeadlineExceeded:
// Loggear y posiblemente retry con contexto renovado
case codes.ResourceExhausted:
// Implementar circuit breaker
default:
// Manejo genérico
}
}
}Configurar timeouts es crítico: usa context.WithTimeout en el cliente y verifica ctx.Err() en el servidor para abortar operaciones largas.
Caso de estudio
Sistema de pagos en e-commerce con microservicios: Servicio de Ordenes llama a Servicio de Pagos. Durante Black Friday, el servicio de pagos sufre alta carga.
| Escenario | Código gRPC | Acción en Cliente | Impacto Usuario |
|---|---|---|---|
| Pago procesado exitosamente | OK | Confirmar orden | Orden completada |
| Timeout de 2 segundos excedido | DEADLINE_EXCEEDED | Retry 1 vez con nuevo timeout de 5s | Ligera demora |
| Servicio de pagos caído | UNAVAILABLE | Circuit breaker abre, fallback a cache | Mensaje "Reintentar más tarde" |
| Tarjeta inválida | INVALID_ARGUMENT | Mostrar error inmediato | Corregir datos |
En producción, monitorea la distribución de códigos de estado: más del 1% de DEADLINE_EXCEEDED puede indicar necesidad de escalar o optimizar.
Errores comunes
- Usar timeouts genéricos: No aplicar timeouts específicos por operación. Solución: Define timeouts basados en percentiles P99 de latencia histórica.
- Ignorar códigos de estado: Tratar todos los errores igual. Solución: Implementar lógica de recuperación diferenciada por código.
- Retry infinito: Reintentar en errores no retryables como INVALID_ARGUMENT. Solución: Usar bibliotecas como retry-go con políticas configuradas.
- No propagar contextos: Perder información de deadline en llamadas anidadas. Solución: Pasar siempre el contexto original o derivado.
- Falta de circuit breakers: Continuar llamando a servicios caídos. Solución: Integrar patrones como hystrix o resilience4j.
Checklist de dominio
- ¿Configuras timeouts diferentes para operaciones de lectura vs escritura?
- ¿Tu cliente distingue entre errores retryables y no retryables?
- ¿Implementas backoff exponencial con jitter para retries?
- ¿Monitoreas la tasa de códigos DEADLINE_EXCEEDED por servicio?
- ¿Usas circuit breakers para servicios críticos?
- ¿Propagas contextos correctamente en toda la cadena de llamadas?
- ¿Tienes fallbacks definidos para cuando los servicios están UNAVAILABLE?
Implementar cliente resiliente con retry y circuit breaker
En este ejercicio, mejorarás un cliente gRPC básico para que maneje errores de producción reales.
- Configura el entorno: Clona el repositorio con un servicio de simulación que devuelve errores aleatorios (UNAVAILABLE, DEADLINE_EXCEEDED, RESOURCE_EXHAUSTED).
- Implementa retry inteligente: Modifica el cliente para reintentar solo en códigos retryables (UNAVAILABLE, DEADLINE_EXCEEDED) con backoff exponencial: 100ms, 200ms, 400ms, máximo 3 intentos.
- Añade circuit breaker: Configura un circuit breaker que se abra después de 5 fallos consecutivos y se cierre tras 30 segundos. Usa la biblioteca "goresilience" o similar.
- Simula carga: Ejecuta 1000 llamadas concurrentes y registra: éxitos, fallos por tipo de error, y activaciones del circuit breaker.
- Optimiza: Ajusta los timeouts basado en los resultados: si más del 5% son DEADLINE_EXCEEDED, aumenta el timeout inicial.
Pistas
- Usa status.FromError() para obtener el código gRPC del error.
- Para el circuit breaker, considera implementar un patrón de estado (closed, open, half-open).
- Prueba con diferentes tasas de error en el servicio simulado para ver cómo se comporta tu cliente.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.
Sigue con Implementación Avanzada de gRPC y Protocol Buffers para Microservicios
Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.
Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.