eduardweb.
DevOps & VPSIntermediar#nodejs#devops#pm2#monitoring

Healthcheck care chiar funcționează pentru PM2: de ce statusul verde e o minciună

De Gabriela Neagu, 11 oct. 2026 · 6 vizualizări · 3 like-uri

Postat acum 4 zile
javascript
const express = require('express');
const { pool } = require('./db');

const app = express();

// Măsurăm event loop lag-ul în timp real
let eventLoopLag = 0;
setInterval(() => {
  const start = Date.now();
  setImmediate(() => {
    eventLoopLag = Date.now() - start;
  });
}, 1000);

app.get('/healthz', async (req, res) => {
  // 1. Verificăm dacă event loop-ul e sugrumat
  if (eventLoopLag > 300) {
    return res.status(503).json({
      status: 'unhealthy',
      reason: `Event loop lag too high: ${eventLoopLag}ms`
    });
  }

  // 2. Ping la DB cu timeout agresiv (max 1s)
  try {
    const timeoutPromise = new Promise((_, reject) =>
      setTimeout(() => reject(new Error('DB Timeout')), 1000)
    );
    
    await Promise.race([
      pool.query('SELECT 1'),
      timeoutPromise
    ]);

    return res.status(200).json({ status: 'healthy', lag: eventLoopLag });
  } catch (err) {
    return res.status(503).json({
      status: 'unhealthy',
      reason: err.message
    });
  }
});

Toți am trecut prin asta: te uiți în consolă, pm2 status arată frumos cu verde aprins, uptime 40 de zile, memorie stabilă. Doar că utilizatorii se lovesc de timeout-uri și Nginx aruncă 502 Bad Gateway pe bandă rulantă.

PM2 e bun la ce știe să facă, dar are o definiție extrem de simplistă a vieții: dacă procesul are PID pe OS și nu a dat exit(1), el presupune că ești fericit. Dacă ai un event loop înghețat pe Node.js sau conexiunea la Postgres e într-o stare de zombie, PM2 n-are niciun habar.

Ce ratează PM2 când îți zice că procesul e „online”

Am pățit treaba asta anul trecut pe un serviciu de procesare plăți cu vreo 4.000 req/min. Un coleg a băgat un regex nesimțit pe un payload de webhook fără să-și dea seama de ReDoS. Event loop-ul a murit instantaneu la 100% CPU pe un core. Procesul nu a crăpat, nu a dat eroare neprinsă, deci PM2 n-a mișcat un deget timp de 20 de minute până când a sunat PagerDuty.

Pe scurt, PM2 nu prinde:

  • Event loop lag extrem: procesul e ocupat cu ceva sincron și nu mai preia nimic din coadă.
  • Pool-uri de conexiuni blocate: DB-ul s-a restartat, driverul tău nu s-a reconectat corect, iar noile query-uri stau la infinit într-un queue.
  • Saturarea threadpool-ului libuv: dacă faci crypto sincron sau I/O blocat de fișiere mari, HTTP worker-ul nu mai răspunde.

Singurul lucru pe care PM2 îl știe nativ e max_memory_restart. Îl ții la 1GB, dacă trece de 1GB îi dă restart. Util, dar primitiv.

Cum construiești un healthcheck real

Dacă pui un endpoint /healthz care returnează doar res.json({ status: 'ok' }), te minți singur. Dacă event loop-ul are un lag de 800ms, răspunsul ăla vine, dar restul aplicației gâfâie.

Ai nevoie de două tipuri de verificări combinate într-un singur răspuns rapid: lag-ul intern și dependențele critice cu timeout strict. Codul de mai jos e fix abordarea pe care o punem noi în producție.

Câteva reguli de fier pentru endpoint-ul ăsta:

  1. Timeout pe query-ul de DB: Maximum 1000-1500ms. Dacă DB-ul nu răspunde într-o secundă la un SELECT 1, nodul ăla nu e sănătos oricum.
  2. Prag de event loop lag: Dacă o iterație simplă de setImmediate durează mai mult de 300ms, refuză traficul.
  3. Fără cache pe răspuns: Vrei starea exactă din secunda aia.

Trade-off-ul: watchdog intern vs agresivitate

Dacă faci healthcheck-ul prea sensibil, ai belit-o în direcția opusă. O mică sughițătură de rețea între worker și DB de 200ms îți va omorî procesul când n-ar trebui.

Pentru un setup stabil, noi legăm endpoint-ul de un script separat de monitorizare (sau de dockcheck / Nginx upstream healthcheck) care cere un failure de 3 ori consecutiv înainte să ceară pm2 reload <id>. Nu lăsa aplicația să-și dea singură process.exit(1) la prima eroare tranzitorie de rețea, că riști o cascadă de restarturi unde pică toate instanțele deodată.

Voi cum monitorizați procesele Node în afara metricilor clasice de CPU/RAM?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.