Por qué se satura la cola de jobs cuando lanzas demasiados background jobs individuales
Este es uno de esos problemas que aparecen “de repente” después de meses funcionando bien: un buen día, SM37 se llena de jobs en estado Liberado que no arrancan, o que arrancan con horas de retraso respecto a la hora planificada. La reacción típica es pedir más procesos de fondo (BTC) en RZ04 y santas pascuas. Aguanta unas semanas más y vuelve a pasar.
El síntoma
En SM37 ves decenas (o cientos) de jobs con nombres casi idénticos —ZINTERFAZ_PEDIDO_000123, ZINTERFAZ_PEDIDO_000124…— todos planificados casi al mismo minuto. En SM66 los procesos BTC disponibles están todos ocupados, y en SM50 ves que la mayoría lleva segundos de ejecución real dentro de minutos de cola.
La causa real
El problema casi nunca es “faltan procesos de fondo”. El problema es el diseño: alguien decidió que cada documento (un pedido, una factura, un IDoc) lanzara su propio job individual en lugar de procesar varios documentos por ejecución. Es una decisión que parece razonable al principio —aislar cada documento simplifica el manejo de errores, cada job tiene su propio log— pero no escala:
- Cada job consume un proceso BTC completo desde que se libera hasta que termina, aunque el trabajo real dure dos segundos.
- El planificador de jobs (
SAPMSSY6/ gestión de jobs) tiene que evaluar la cola en cada ciclo, y con cientos de entradas eso también tiene coste. - Si el volumen de documentos crece un 30%, la cola no crece un 30%: se satura, porque los procesos BTC son un recurso fijo compartido con otros procesos de la instancia (spool, actualización, etc. si no están bien separados).
Cómo confirmarlo
Antes de tocar nada, mido. Un par de comprobaciones rápidas:
" Cuántos jobs de la misma familia hay activos/planificados ahora mismo
SELECT jobname, status, sdlstrtdt, sdlstrttm
FROM tbtco
INTO TABLE @DATA(lt_jobs)
WHERE jobname LIKE 'ZINTERFAZ_PEDIDO%'
AND status IN ( 'R', 'Y' ). " Running, Released/Scheduled
Si lt_jobs tiene cientos de líneas para una ventana de pocos minutos, ahí está el problema. También merece la pena mirar RZ04/SM61 para ver cuántos procesos BTC hay realmente disponibles en la instancia frente a los que necesitarías si cada documento consume uno.
La solución que funciona
No es aumentar procesos BTC (eso es parchear sin arreglar). Las dos soluciones que de verdad escalan:
- Procesamiento por lotes dentro de un mismo job. En lugar de un job por documento, un job que procesa N documentos en bucle interno, con
COMMIT WORKpor documento (para no perder todo el lote si falla uno) y su propio log de errores en una tabla Z, no en el log del job. - Paralelización controlada con
CALL FUNCTION ... STARTING NEW TASKcuando el volumen es alto y el procesamiento por documento es pesado. Aquí sí quieres varios procesos en paralelo, pero un número acotado y conocido (por ejemplo, 4 o 6 tareas paralelas), no uno por documento.
Con cualquiera de las dos, pasas de “cientos de jobs de dos segundos peleándose por la cola” a “un puñado de jobs que hacen un trabajo real y predecible”. El manejo de errores por documento se mantiene con una tabla de log propia, no con el log estándar del job — que es justo lo que hacía atractivo el enfoque original.
La lección
Un job por documento es fácil de programar y difícil de operar. Cuando el volumen crece, el cuello de botella nunca es la CPU: es la cola de procesos BTC, un recurso compartido y finito. Diseña para lotes desde el principio, aunque el volumen inicial parezca pequeño.