Ir al contenido

Ingeniería de sistemas

Ingeniería de colas y trabajos en segundo plano

Colas que puede dejar en paz - trabajos idempotentes, reintentos con espera creciente, una ruta de fallo que alguien mira de verdad, y workers que sobreviven a un despliegue sin perder trabajo.

Una cola es la parte de una aplicación Laravel más fácil de añadir y más difícil de operar. dispatch() es una línea, y todo lo que marca la diferencia entre una cola y una cola fiable ocurre después de esa línea.

Las cuatro preguntas que una cola tiene que responder

¿Qué pasa cuando el trabajo falla? No si falla. Una API de terceros agota el tiempo de espera, un registro se borra entre el envío y la ejecución, un despliegue reinicia el worker a mitad del trabajo. La respuesta tiene que estar escrita como una política de reintentos con espera creciente, un número máximo de intentos y un destino para lo que siga fallando al final.

¿Qué pasa cuando se ejecuta dos veces? La entrega al menos una vez es la garantía normal, lo que significa que cada trabajo debe ser seguro de repetir o estar protegido por algo que haga inofensiva la repetición. Un correo enviado dos veces es una vergüenza. Un pago cobrado dos veces es una devolución y un hilo de soporte.

¿Quién se entera? Una tabla failed_jobs que se llena en silencio es el fallo de producción más habitual que nos piden mirar, y nunca es realmente un fallo de la cola. El trabajo falló, el framework lo registró exactamente como estaba previsto, y no había nada enganchado al registro.

¿Qué pasa durante un despliegue? Un worker que sostiene un trabajo mientras el código cambia debajo de él o se reinicia limpiamente o se mata. Cuál de las dos depende de una configuración que la mayoría de los equipos hereda en lugar de elegir.

Qué hacemos

Hacer los trabajos idempotentes. Un identificador que el trabajo lleva consigo, aplicado donde el efecto aterriza de verdad: una restricción única, una clave de idempotencia en el proveedor de pagos, una transición de estado que solo puede ocurrir una vez. No un comprobar-y-actuar en PHP, que dos workers atravesarán a la vez el día en que importe.

Fijar políticas de reintento por trabajo, no por aplicación. Un fallo HTTP transitorio quiere varios intentos con retraso creciente. Un fallo de validación quiere cero: reintentarlo solo quema la cola y retrasa todo lo que va detrás. Distinguirlos es un cambio de dos líneas y casi nunca se hace.

Dar a los fallos un sitio adonde ir. Trabajos fallidos comunicados a lo que su equipo ya mira, con contexto suficiente para actuar. Una ruta de descarte para lo que no se puede reintentar. Una alerta sobre la tasa y no sobre el evento individual, para que sea señal y no ruido.

Dimensionar la topología. Separar colas por requisito de latencia en lugar de por funcionalidad, para que una exportación nocturna no pueda retrasar un restablecimiento de contraseña. Workers dimensionados según la forma real del trabajo. Horizon configurado con supervisores que encajen con eso, y métricas que hagan visible un atasco creciente antes de que sea un incidente.

Hacer que el trabajo largo sobreviva. Trabajos agrupados con progreso, troceados para que un reinicio cueste un trozo y no la ejecución entera, y con una forma de reanudar en lugar de empezar de nuevo.

El trabajo programado, que tiene los mismos problemas

El planificador recibe menos atención que la cola y falla de las mismas formas. Una tarea que se solapa consigo misma porque la ejecución anterior sigue en marcha. Una tarea que deja de funcionar en silencio porque la entrada de cron estaba en un servidor que se reemplazó. Una tarea cuyo fallo es una línea de registro que nadie lee.

Tratamos las tareas programadas como trabajos con un disparador: protección contra solapamiento donde importa, un latido para que se note una tarea que deja de ejecutarse, y la misma ruta de fallo que todo lo demás.

Cómo transcurre un encargo

Mándenos las clases de los jobs y, si las guarda, una semana de registros de trabajos fallidos. Lo que ya ha salido mal dice más sobre el diseño que el código.

Lo que vuelve es un alcance: cada job con su comportamiento ante fallos, la topología de colas, la monitorización, y qué entra en la fase uno. Lleva un precio, y el contrato se refiere a él y no a una conversación.

El trabajo llega como pull requests revisables en su repositorio, con el comportamiento de reintento e idempotencia probado en lugar de descrito.

Qué recibe

Una revisión de cada trabajo y cada tarea programada de la aplicación con su comportamiento ante fallos documentado, las correcciones como pull requests revisables, la topología de colas y la configuración de workers como código, y la monitorización conectada a lo que ya use.

El entregable que nos importa es el más difícil de enseñar: una cola en la que nadie ha pensado en un mes, porque no ha necesitado a nadie.

Todo el diseño descansa sobre una suposición: cada trabajo se ejecutará dos veces. La mayoría de los fallos de cola son una violación de ella. El segundo más común es un worker que todavía ejecuta el código de la semana pasada, un fallo de despliegue que se presenta como un fallo de cola. Si los trabajos son lentos y no incorrectos, se empieza por el trabajo de rendimiento.

Alcance y condiciones

Modelo de colaboración
Alcance cerrado, acordado por escrito antes de empezar. No es una tarifa por día contra una lista abierta.
Precio y plazo
Los dos se fijan por proyecto, una vez fijado el alcance. Se ofertan juntos, antes de construir nada.
Qué necesitamos de usted
Una persona que pueda aprobar decisiones, y acceso a su repositorio y a su gestor de incidencias.
No incluido
Todo lo que quede fuera del alcance acordado. Pasa a ser su propio alcance, no una modificación.
Costes de terceros
El alojamiento, las licencias, las tarifas de API y las suscripciones SaaS los contrata y paga usted.
Facturación
Codefacture Yazılım A.Ş., Türkiye. EUR, USD o GBP por transferencia, sin IVA turco en servicios exportados.

Preguntas frecuentes

Usamos el driver de cola de base de datos. ¿Es un problema?
Por sí solo no, y para un volumen moderado es una elección razonable con un servicio menos que operar. Se convierte en problema cuando la tabla de trabajos es además su tabla con más escrituras, o cuando la contención del sondeo empieza a aparecer en el registro de consultas lentas. Le diremos de qué lado de esa línea está en lugar de recomendar Redis por reflejo.
¿Necesitamos Horizon?
Si está en Redis, sí, y no por el panel sino por la supervisión y las métricas. Sin él, un worker que muere es silencio, y el silencio no se distingue de una cola vacía hasta que se lo dice un cliente.
Nuestra tabla failed_jobs tiene miles de filas que nadie ha leído.
Es el hallazgo más frecuente que tenemos. No es un problema de colas, es un problema de monitorización: los fallos se registran exactamente como está previsto y no hay nada enganchado al registro. Arreglarlo suele ser una hora de trabajo y cambia la fiabilidad de todo el sistema.
¿Se pueden hacer seguros los reintentos si el trabajo mueve dinero?
Sí, y hay que hacerlo. El mecanismo es una clave de idempotencia que el trabajo lleva consigo y que se aplica en el punto donde ocurre el efecto - el proveedor de pagos, o una restricción única en su propia base de datos. Un trabajo que no es seguro de ejecutar dos veces es un trabajo que acabará ejecutándose dos veces.
Llamar+1 848 272 7583WhatsApp+90 850 308 5436Correoinfo@codefacture.comPágina de contacto