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

Healthcheck care chiar funcționează pentru PM2. Ce scapă monitorizării standard?

De Alexandru Matei, 12 iul. 2026 · 16 vizualizări · 3 like-uri

Postat 12 iul. 2026
javascript
const express = require('express');
const router = express.Router();
const db = require('./db'); 

// Măsurăm lag-ul pe event loop
let eventLoopLag = 0;
setInterval(() => {
  const start = Date.now();
  setTimeout(() => {
    eventLoopLag = Date.now() - start;
  }, 0);
}, 1000).unref();

router.get('/healthz', async (req, res) => {
  try {
    // 1. Verificăm conexiunea la baza de date
    await db.raw('SELECT 1'); 
    
    // 2. Verificăm dacă event loop-ul e blocat grav (peste 200ms lag)
    if (eventLoopLag > 200) {
      return res.status(503).json({ status: 'unhealthy', reason: 'Event loop blocked', lag: eventLoopLag });
    }

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

Ne-am lovit toți de asta la un moment dat. Te uiți în pm2 list, totul e verde, statusul e "online", dar pe Slack încep să curgă mesaje că site-ul e jos. PM2 e excelent pentru managementul proceselor, dar este incredibil de prost la a detecta dacă aplicația ta chiar funcționează sau doar consumă resurse degeaba la nivel de sistem.

Am pățit asta acum doi ani pe un proiect cu vreo 12.000 de utilizatori activi zilnic. Aveam un memory leak masiv care bloca complet event loop-ul. Procesul Node.js încă rula, așa că pentru PM2 totul era perfect. În realitate, serverul dădea timeout la orice request primit. PM2 monitorizează doar dacă PID-ul (Process ID) trimite semnale de viață la nivel de sistem de operare. Dacă codul tău e blocat într-o buclă infinită sau conexiunea la baza de date a crăpat complet, PM2 nu are de unde să știe asta. El vede doar că procesul node nu a murit.

De ce un endpoint simplu de ping nu e de ajuns

Mulți developeri pun un endpoint /ping care returnează doar status 200 OK. E mai bine decât nimic, dar rezolvă doar 10% din problemă. Dacă baza de date e picată, endpoint-ul tău de ping s-ar putea să răspundă în continuare cu succes pentru că nu interacționează deloc cu ea.

Un healthcheck real trebuie să fie "deep". Asta înseamnă că trebuie să testeze dependențele critice fără de care aplicația nu poate funcționa: baza de date, cache-ul (cum ar fi Redis) și lag-ul de pe event loop.

Trade-off-ul dintre siguranță și boot-loop

Aici apare o problemă delicată. Dacă pui un healthcheck prea agresiv, riști să îți bagi aplicația într-un boot-loop infinit. Am pățit asta când am setat ca load balancer-ul să dea restart la instanță dacă healthcheck-ul dădea timeout mai mult de 3 secunde. În momentele de trafic intens, baza de date răspundea mai greu, healthcheck-ul pica, iar PM2 repornea procesul exact când nu trebuia, punând și mai multă presiune pe baza de date.

Soluția este să ai praguri diferite. De exemplu, dacă baza de date nu răspunde timp de 30 de secunde, abia atunci marchezi instanța ca nesănătoasă. Pentru asta, folosește un sistem cu două endpoint-uri: unul de liveness (aplicația e în viață) și unul de readiness (aplicația e gata să primească trafic).

Pentru a integra asta cu PM2 în producție, cea mai curată metodă este să folosești gracefulReload. Când faci deploy, trimiți semnalul de reload, iar PM2 va aștepta ca noua instanță să trimită semnalul process.send('ready') înainte să o oprească pe cea veche. Combină asta cu codul de mai jos pentru a te asigura că pornești doar instanțe complet funcționale.

Voi cum gestionați alertele când PM2 arată verde, dar aplicația e în comă? Folosiți un serviciu extern sau aveți scripturi custom de monitorizare?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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