module.exports = {
apps: [{
name: "api-production",
script: "./dist/server.js",
instances: "max",
exec_mode: "cluster",
wait_ready: true,
listen_timeout: 10000,
kill_timeout: 3000,
max_memory_restart: "500M",
autorestart: true,
watch: false,
env: {
NODE_ENV: "production",
PORT: 3000
}
}]
};Să pornești o aplicație de Node.js în producție cu un simplu pm2 start app.js e primul pas spre un weekend stricat de apeluri de la clienți. Am trecut prin asta acum vreo 5 ani la un proiect cu peste 12k utilizatori activi, când serverul a crăpat fiindcă s-a umplut discul de loguri, iar restartul manual a durat destul cât să pierdem lead-uri importante. Soluția reală e un fișier de configurare robust, adică ecosystem.config.js.
Nu ai nevoie de Kubernetes de la primul deploy ca să ai reziliență și scalare. PM2 știe să facă asta extrem de bine dacă îi dai instrucțiunile corecte.
De la fork la Cluster Mode și Graceful Reload
Implicit, PM2 pornește aplicația în mod fork. Asta înseamnă un singur proces rulat pe un singur nucleu de procesor. Dacă ai un server VPS cu 4 nuclee, folosești doar 25% din puterea pentru care plătești. Trecerea la instances: 'max' activează modul cluster, unde PM2 devine un load balancer nativ care împarte traficul între instanțe.
Dar aici apare un trade-off important pe care mulți îl ignoră. Dacă aplicația ta ține sesiuni direct în memorie sau folosește WebSocket-uri simple fără un adaptor precum Redis, cluster mode o să-ți dea peste cap logica aplicației. Userul va nimeri pe instanțe diferite la fiecare request. Dacă ai rezolvat această arhitectură (folosind Redis sau sesiuni stateless), primești la schimb cel mai mare avantaj: pm2 reload în loc de restart.
Spre deosebire de un restart clasic (care oprește tot și pornește din nou, lăsând userii cu erori 502 timp de câteva secunde), comanda reload repornește procesele pe rând, unul câte unul. Zero downtime deploy garantat.
Auto-restart la OOM (Out of Memory)
Node.js are prostul obicei de a consuma RAM până când sistemul de operare decide să-i dea kill (OOM Killer). Am pățit asta din cauza unui memory leak ascuns într-o librărie de generare de PDF-uri. Serverul murea complet o dată la două zile.
În loc să las tot serverul să se blocheze, am adăugat parametrul max_memory_restart. Setat la 500M (sau în funcție de resursele tale), acesta îi spune lui PM2 să monitorizeze consumul. Când o instanță trece de 500MB, PM2 îi dă un restart curat în fundal. Este, evident, un workaround temporar până găsești bug-ul din cod, dar îți salvează reputația în fața clienților.
Ca să funcționeze corect graceful reload în acest scenariu, asigură-te că procesul tău ascultă de semnalul SIGINT trimis de PM2 și închide conexiunile la baza de date înainte de a se opri (folosind proprietatea kill_timeout din config).
Logurile care îți blochează discul
Implicit, PM2 scrie tot ce prinzi în console.log în fișiere text simple, fără limită de dimensiune. La un proiect cu trafic mediu, te poți trezi în 3 luni cu un fișier de loguri de 30GB care îți umple tot discul și blochează baza de date.
Pentru asta, nu te chinui cu scripturi de bash. Instalează modulul lor oficial direct pe server:
pm2 install pm2-logrotate
Acesta va tăia automat logurile când ajung la 10MB și va păstra doar ultimele 30 de arhive. Simplu, eficient și fără bătăi de cap.
Voi cum gestionați procesele de Node în producție? Mergeți direct pe Docker sau PM2 e încă regele pe VPS-uri clasice?