eduardweb.
DevOps & VPSIntermediar#devops#pm2#backend#monitoring#node-js

De ce statusul "online" din PM2 te minte și cum faci un healthcheck real

De Delia Petre, 26 apr. 2026 · 1 vizualizări · 3 like-uri

Postat acum 1 zi
javascript
const express = require('express');
const mongoose = require('mongoose');
const app = express();

app.get('/health', async (req, res) => {
  const healthcheck = {
    uptime: process.uptime(),
    message: 'OK',
    timestamp: Date.now()
  };
  try {
    // Verificăm dacă DB-ul e chiar legat
    if (mongoose.connection.readyState !== 1) {
      throw new Error('Database not connected');
    }
    res.send(healthcheck);
  } catch (error) {
    healthcheck.message = error.message;
    res.status(503).send(healthcheck);
  }
});

Dacă te bazezi pe pm2 status ca să știi dacă aplicația ta e în picioare, am o veste proastă pentru tine: trăiești periculos. Am pățit-o acum vreo 3 ani la un proiect cu vreo 12.000 de useri activi, unde totul apărea cu verde în consolă, dar în realitate API-ul dădea timeout pe bandă rulantă.

Problema e simplă. PM2 monitorizează procesul la nivel de sistem de operare. Dacă PID-ul există și procesul n-a crăpat cu un exit code fatal, PM2 o să-ți raporteze fericit statusul „online”. Dar ce se întâmplă când Event Loop-ul tău e blocat de o funcție sincronă nenorocită sau când conexiunea la baza de date a murit, dar procesul Node.js încă respiră? PM2 n-are nicio idee.

Capcana statusului "online"

Node.js e „single-threaded” (mă rog, știm noi cum e, dar pentru Event Loop contează asta). Am avut cazul unui script care făcea un procesat masiv de JSON-uri într-o buclă. Procesul era „online”, CPU-ul stătea în 100%, dar orice request HTTP nou stătea la coadă până când expira timeout-ul din Nginx. Din perspectiva PM2, totul era perfect.

Altă fază clasică: baza de date pică. Aplicația ta pornește, dar nu se poate conecta. Dacă n-ai pus un process.exit(1) în catch-ul de la conexiune, aplicația rămâne într-un stadiu de „zombie”. E vie, dar inutilă. PM2 o vede online, load balancer-ul îi trimite trafic, userul vede erori.

Cum construiești un healthcheck care chiar zice ceva

Soluția nu e să te uiți la proces, ci să întrebi aplicația dacă „se simte bine”. Eu folosesc mereu un endpoint dedicat, de obicei /health sau /_status. Dar atenție, nu pune doar un res.send('ok'). Asta testează doar dacă serverul HTTP răspunde, ceea ce e un început, dar nu e destul.

Un healthcheck serios trebuie să verifice:

  1. Conexiunea la baza de date (un simplu SELECT 1 sau db.command({ ping: 1 })).
  2. Conexiunea la Redis sau cozi de mesaje (RabbitMQ/Kafka).
  3. Timpul de răspuns (dacă durează 5 secunde să-mi zică că e OK, clar avem o problemă de lag).

La proiectul menționat mai sus, am introdus un check care verifica și heap memory-ul. Dacă săream de 80% din memoria alocată constant, forțam un restart înainte să dea V8-ul Out of Memory. Am redus incidentele de tip „silent crash” cu aproape 40% în prima lună.

Trade-off: Deep vs Shallow healthcheck

Aici e o discuție întreagă. Dacă faci un healthcheck prea „deep” (verifici 10 servicii externe), riști să-ți omori singur aplicația. Dacă pică un API terț de care nu depinde funcționarea de bază, nu vrei ca PM2 să-ți dea restart la proces în buclă.

Trade-off-ul meu: în healthcheck-ul pentru PM2/Load Balancer verific doar resursele critice fără de care aplicația e complet inutilă (DB local, Redis pentru sesiuni). Restul le pun într-un alt endpoint de monitorizare (ex. /health/details) pe care îl verifică sistemul de alerting (Grafana/Prometheus), dar care nu declanșează restarturi automate.

Ce facem cu PM2?

PM2 are un modul numit pm2-server-monit sau poți folosi pm2 plus (varianta plătită), dar sincer, cea mai robustă metodă rămâne un script extern sau configurarea corectă a max_memory_restart și un cron care dă un ping în endpoint-ul de sănătate.

Dacă ești pe Kubernetes, PM2 e oricum cam redundant, dar pe un VPS clasic, asigură-te că ai măcar graceful reload configurat. Când PM2 dă restart, trimite SIGINT. Dacă aplicația ta nu ascultă de semnalul ăsta ca să închidă conexiunile curat, o să ai downtime la fiecare deploy.

Voi ce verificați în endpoint-ul de health înainte să lăsați traficul să intre în instanță?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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