Per què se satura la cua de jobs quan llances massa background jobs individuals

Llançar un job per document en lloc d'agrupar la feina és un patró habitual a SAP. Per què satura la cua de jobs i com solucionar-ho de veritat.

En aquest article
  1. El símptoma
  2. La causa real
  3. Com confirmar-ho
  4. La solució que funciona
  5. La lliçó

Aquest és un d’aquells problemes que apareixen “de sobte” després de mesos funcionant bé: un bon dia, SM37 s’omple de jobs en estat Alliberat que no arrenquen, o que arrenquen amb hores de retard respecte a l’hora planificada. La reacció típica és demanar més processos de fons (BTC) a RZ04 i santes pasqües. Aguanta unes setmanes més i torna a passar.

El símptoma

A SM37 veus desenes (o centenars) de jobs amb noms gairebé idèntics —ZINTERFAZ_PEDIDO_000123, ZINTERFAZ_PEDIDO_000124…— tots planificats gairebé al mateix minut. A SM66 els processos BTC disponibles estan tots ocupats, i a SM50 veus que la majoria porta segons d’execució real dins de minuts de cua.

La causa real

El problema gairebé mai és “falten processos de fons”. El problema és el disseny: algú va decidir que cada document (una comanda, una factura, un IDoc) llancés el seu propi job individual en lloc de processar diversos documents per execució. És una decisió que sembla raonable al principi —aïllar cada document simplifica la gestió d’errors, cada job té el seu propi log— però no escala:

  • Cada job consumeix un procés BTC complet des que s’allibera fins que acaba, encara que la feina real duri dos segons.
  • El planificador de jobs (SAPMSSY6 / gestió de jobs) ha d’avaluar la cua a cada cicle, i amb centenars d’entrades això també té cost.
  • Si el volum de documents creix un 30%, la cua no creix un 30%: se satura, perquè els processos BTC són un recurs fix compartit amb altres processos de la instància (spool, actualització, etc. si no estan ben separats).

Com confirmar-ho

Abans de tocar res, mesuro. Un parell de comprovacions ràpides:

" Quants jobs de la mateixa família hi ha actius/planificats ara mateix
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 té centenars de línies per a una finestra de pocs minuts, aquí està el problema. També val la pena mirar RZ04/SM61 per veure quants processos BTC hi ha realment disponibles a la instància davant dels que necessitaries si cada document consumeix un procés.

La solució que funciona

No és augmentar processos BTC (això és pedaçar sense arreglar). Les dues solucions que de veritat escalen:

  1. Processament per lots dins d’un mateix job. En lloc d’un job per document, un job que processa N documents en bucle intern, amb COMMIT WORK per document (per no perdre tot el lot si un falla) i el seu propi log d’errors en una taula Z, no en el log del job.
  2. Paral·lelització controlada amb CALL FUNCTION ... STARTING NEW TASK quan el volum és alt i el processament per document és pesat. Aquí sí que vols diversos processos en paral·lel, però un nombre acotat i conegut (per exemple, 4 o 6 tasques paral·leles), no un per document.

Amb qualsevol de les dues, passes de “centenars de jobs de dos segons barallant-se per la cua” a “un grapat de jobs que fan una feina real i predictible”. La gestió d’errors per document es manté amb una taula de log pròpia, no amb el log estàndard del job — que és justament el que feia atractiu l’enfocament original.

La lliçó

Un job per document és fàcil de programar i difícil d’operar. Quan el volum creix, el coll d’ampolla mai és la CPU: és la cua de processos BTC, un recurs compartit i finit. Dissenya per lots des del principi, encara que el volum inicial sembli petit.

Escrit per Juanma Vallecillos

Desenvolupador ABAP i consultor SAP FI/MM a VISEO Iberia. T'ha passat alguna cosa semblant o veus una altra manera de resoldre-ho? M'encantarà llegir-ho.