PM2 Process Management for Node.js in Production

PM2 process management for Node.js production: ecosystem file configuration, zero-downtime restarts, log management, monitoring, clustering, and deployment workflows.

E
ECOSIRE Research and Development Team
|19 मार्च 202610 मिनट पढ़ें2.2k शब्द|

उत्पादन में Node.js के लिए PM2 प्रक्रिया प्रबंधन

जब आपका Node.js एप्लिकेशन 2 बजे पूर्वाह्न में क्रैश हो जाता है, तो PM2 उसके स्वचालित रूप से पुनरारंभ होने और आपके उपयोगकर्ताओं को आपके जागने तक एक खाली पृष्ठ देखने के बीच का अंतर है। PM2 एक युद्ध-परीक्षित प्रक्रिया प्रबंधक है जो स्वचालित पुनरारंभ, मल्टी-कोर उपयोग के लिए क्लस्टरिंग, लॉग एकत्रीकरण और शून्य-डाउनटाइम तैनाती को संभालता है - यह सब एक एकल कॉन्फ़िगरेशन फ़ाइल के साथ जो आपके रिपॉजिटरी में रहता है।

यह मार्गदर्शिका एक उत्पादन PM2 सेटअप को कवर करती है जो एक साथ 5 Node.js प्रक्रियाओं को प्रबंधित करता है: Next.js (फ्रंटएंड), NestJS (API), Docusaurus (docs), और दो ब्रांड साइटें। पैटर्न एकल-प्रक्रिया परिनियोजन पर समान रूप से लागू होते हैं।

मुख्य बातें

  • ecosystem.config.cjs फ़ाइल (CommonJS, .js नहीं) ESModule और CommonJS दोनों परियोजनाओं के साथ काम करती है
  • नए पर्यावरण चर लेने के लिए पुनरारंभ करते समय --update-env ध्वज की आवश्यकता होती है
  • .env.local को अपडेट करने के बाद कभी भी --update-env के बिना pm2 restart all का उपयोग न करें
  • उत्पादन में watch: false - फ़ाइल देखने से बिल्ड आउटपुट के साथ अनंत पुनरारंभ लूप होते हैं
  • max_memory_restart प्रक्रिया को स्थायी रूप से बंद किए बिना स्वचालित मेमोरी रिसाव सुरक्षा प्रदान करता है
  • node_args: '--max-old-space-size=4096' मेमोरी-सघन संचालन पर OOM क्रैश को रोकता है
  • PM2 लॉग pm2-logrotate मॉड्यूल के साथ घूमते हैं - इसे PM2 के तुरंत बाद इंस्टॉल करें
  • pm2 save और pm2 startup सर्वर रीबूट के दौरान आपकी प्रक्रिया सूची को बनाए रखते हैं

स्थापना

# Install PM2 globally
npm install -g pm2

# Install the log rotation module immediately
pm2 install pm2-logrotate

# Configure log rotation
pm2 set pm2-logrotate:max_size 50M
pm2 set pm2-logrotate:retain 7
pm2 set pm2-logrotate:compress true
pm2 set pm2-logrotate:dateFormat YYYY-MM-DD

पारिस्थितिकी तंत्र कॉन्फ़िगरेशन फ़ाइल

ecosystem.config.cjs फ़ाइल (ईएसएम और सीजेएस दोनों परियोजनाओं के साथ काम करने के लिए कॉमनजेएस प्रारूप) आपकी सभी प्रक्रियाओं को परिभाषित करती है:

// ecosystem.config.cjs
module.exports = {
  apps: [
    // ─── Next.js Frontend ────────────────────────────────────────────
    {
      name: 'ecosire-web',
      script: 'node_modules/.bin/next',
      args: 'start',
      cwd: '/opt/ecosire/app/apps/web',
      instances: 1,        // Single instance — Next.js handles its own multi-threading
      exec_mode: 'fork',
      env: {
        NODE_ENV: 'production',
        PORT: 3000,
      },
      // Memory management
      max_memory_restart: '1G',
      node_args: '--max-old-space-size=1024',
      // Logging
      out_file: '/var/log/pm2/ecosire-web.out.log',
      error_file: '/var/log/pm2/ecosire-web.err.log',
      merge_logs: true,
      log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
      // Restart behavior
      watch: false,
      restart_delay: 3000,
      max_restarts: 10,
      min_uptime: '30s',   // Must stay up 30s to count as successful start
      autorestart: true,
      // Graceful shutdown
      kill_timeout: 30000, // 30 seconds to shut down gracefully
      wait_ready: true,    // Wait for process.send('ready')
      listen_timeout: 60000,
    },

    // ─── NestJS API ──────────────────────────────────────────────────
    {
      name: 'ecosire-api',
      script: 'dist/main.js',
      cwd: '/opt/ecosire/app/apps/api',
      instances: 2,         // Cluster mode for multi-core utilization
      exec_mode: 'cluster',
      env: {
        NODE_ENV: 'production',
        PORT: 3001,
      },
      max_memory_restart: '512M',
      node_args: '--max-old-space-size=512',
      out_file: '/var/log/pm2/ecosire-api.out.log',
      error_file: '/var/log/pm2/ecosire-api.err.log',
      merge_logs: true,
      log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
      watch: false,
      restart_delay: 2000,
      max_restarts: 10,
      min_uptime: '20s',
      autorestart: true,
      kill_timeout: 15000,
      // Graceful cluster reload support
      listen_timeout: 30000,
    },

    // ─── Docusaurus Docs ─────────────────────────────────────────────
    {
      name: 'ecosire-docs',
      script: 'node_modules/.bin/docusaurus',
      args: 'serve',
      cwd: '/opt/ecosire/app/apps/docs',
      instances: 1,
      exec_mode: 'fork',
      env: {
        NODE_ENV: 'production',
        PORT: 3002,
      },
      max_memory_restart: '256M',
      out_file: '/var/log/pm2/ecosire-docs.out.log',
      error_file: '/var/log/pm2/ecosire-docs.err.log',
      merge_logs: true,
      log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
      watch: false,
      restart_delay: 3000,
      max_restarts: 5,
      min_uptime: '30s',
      autorestart: true,
      kill_timeout: 10000,
    },

    // ─── Brand Site: Odovation ───────────────────────────────────────
    {
      name: 'odovation-web',
      script: 'node_modules/.bin/next',
      args: 'start',
      cwd: '/opt/ecosire/app/apps/odovation',
      instances: 1,
      exec_mode: 'fork',
      env: {
        NODE_ENV: 'production',
        PORT: 3010,
      },
      max_memory_restart: '512M',
      out_file: '/var/log/pm2/odovation-web.out.log',
      error_file: '/var/log/pm2/odovation-web.err.log',
      merge_logs: true,
      log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
      watch: false,
      restart_delay: 3000,
      max_restarts: 10,
      min_uptime: '30s',
      autorestart: true,
    },

    // ─── Brand Site: MuhammadAmir ────────────────────────────────────
    {
      name: 'muhammadamir-web',
      script: 'node_modules/.bin/next',
      args: 'start',
      cwd: '/opt/ecosire/app/apps/muhammadamir',
      instances: 1,
      exec_mode: 'fork',
      env: {
        NODE_ENV: 'production',
        PORT: 3020,
      },
      max_memory_restart: '512M',
      out_file: '/var/log/pm2/muhammadamir-web.out.log',
      error_file: '/var/log/pm2/muhammadamir-web.err.log',
      merge_logs: true,
      log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
      watch: false,
      restart_delay: 3000,
      max_restarts: 10,
      min_uptime: '30s',
      autorestart: true,
    },
  ],
};

कोर पीएम2 कमांड

# Start all processes from ecosystem file
pm2 start ecosystem.config.cjs

# Restart all (with updated environment variables)
pm2 restart ecosystem.config.cjs --update-env

# Graceful reload (zero-downtime for cluster mode)
pm2 reload ecosystem.config.cjs

# Stop all processes
pm2 stop all

# Delete all processes from PM2 registry
pm2 delete all

# Individual process management
pm2 restart ecosire-api
pm2 stop ecosire-docs
pm2 logs ecosire-web --lines 100

# Real-time monitoring dashboard
pm2 monit

# Status overview
pm2 status
pm2 list

सर्वर रिबूट पर स्टार्टअप

स्टार्टअप कॉन्फ़िगरेशन के बिना, सर्वर रीबूट पर सभी PM2 प्रक्रियाएं खो जाती हैं:

# Generate and install the startup script for your init system
pm2 startup
# Copy the output command and run it (it looks like:)
# sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u ubuntu --hp /home/ubuntu

# Save the current process list
pm2 save
# This creates ~/.pm2/dump.pm2 — processes are restored on reboot

# Verify startup works
pm2 resurrect  # Manually restore from dump.pm2

हर बार जब आप प्रक्रियाएँ जोड़ते या हटाते हैं, तो डंप फ़ाइल को अपडेट करने के लिए pm2 save को फिर से चलाएँ।


शून्य-डाउनटाइम परिनियोजन

क्लस्टर मोड में NestJS के लिए, PM2 वास्तविक शून्य-डाउनटाइम पुनः लोड का समर्थन करता है:

# Reload restarts workers one at a time (zero-downtime)
# Old workers handle requests while new ones start
pm2 reload ecosire-api

# vs restart — kills all workers simultaneously (brief downtime)
pm2 restart ecosire-api

Next.js (जो फोर्क मोड, एकल उदाहरण में चलता है) के लिए, शून्य-डाउनटाइम के लिए एक अलग दृष्टिकोण की आवश्यकता होती है। अपने ऐप से स्टार्टअप सिग्नल के साथ wait_ready + listen_timeout कॉन्फ़िगरेशन का उपयोग करें:

// apps/web — this is handled automatically by Next.js
// But for NestJS, send the ready signal explicitly:

// apps/api/src/main.ts
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3001);

  // Signal PM2 that the process is ready
  if (process.send) {
    process.send('ready');
  }
}

bootstrap();

लॉग प्रबंधन

यदि प्रबंधित नहीं किया गया तो PM2 लॉग आपकी डिस्क को भर सकते हैं। लॉग रोटेशन को तुरंत कॉन्फ़िगर करें:

# Install log rotation module
pm2 install pm2-logrotate

# Configuration
pm2 set pm2-logrotate:max_size 50M       # Rotate when log reaches 50MB
pm2 set pm2-logrotate:retain 7           # Keep 7 days of logs
pm2 set pm2-logrotate:compress true      # Gzip rotated logs
pm2 set pm2-logrotate:dateFormat YYYY-MM-DD
pm2 set pm2-logrotate:workerInterval 30  # Check rotation interval (seconds)
pm2 set pm2-logrotate:rotateInterval '0 0 * * *'  # Daily at midnight

उपयोगी लॉग कमांड:

# View all logs combined
pm2 logs

# View specific process logs
pm2 logs ecosire-api

# View with timestamps
pm2 logs --timestamp

# Flush all log files
pm2 flush

# Tail error logs only
pm2 logs ecosire-api --err --lines 200

निगरानी और मेट्रिक्स

PM2 प्लस (पूर्व में कीमेट्रिक्स) क्लाउड-आधारित निगरानी प्रदान करता है। स्व-होस्टेड निगरानी के लिए:

# Built-in terminal dashboard
pm2 monit

# Get JSON status for scripting/monitoring integration
pm2 jlist    # JSON process list
pm2 prettylist  # Formatted process list

# Integrate with your monitoring stack
pm2 set pm2-server-monit:interval 5  # Metrics collection interval

उत्पादन की निगरानी के लिए, पीएम2 मेट्रिक्स को प्रोमेथियस पर प्रदर्शित करें:

npm install -g pm2-prometheus-exporter
pm2 set pm2-prometheus-exporter:port 9209

# Scrape in Prometheus config:
# - job_name: pm2
#   static_configs:
#     - targets: ['localhost:9209']

परिनियोजन स्क्रिप्ट एकीकरण

एक विशिष्ट परिनियोजन क्रम:

#!/bin/bash
# scripts/deploy-production.sh

set -e

echo "=== Starting deployment ==="

# 1. Pull latest code
git pull origin main

# 2. Install dependencies
pnpm install --frozen-lockfile

# 3. Build all apps (with Turbo remote cache)
TURBO_TOKEN="$TURBO_TOKEN" TURBO_TEAM="$TURBO_TEAM" \
  npx turbo run build

# 4. Run database migrations
pnpm --filter @ecosire/db db:migrate

# 5. Restart PM2 processes
# --update-env picks up changes in .env.local
pm2 restart ecosystem.config.cjs --update-env

# 6. Wait for processes to stabilize
sleep 10

# 7. Health checks
curl -f https://ecosire.com/ -o /dev/null -s || {
  echo "Web health check failed — rolling back"
  git revert HEAD --no-edit
  pm2 restart ecosystem.config.cjs --update-env
  exit 1
}

curl -f https://api.ecosire.com/api/health -o /dev/null -s || {
  echo "API health check failed — rolling back"
  git revert HEAD --no-edit
  pm2 restart ecosystem.config.cjs --update-env
  exit 1
}

# 8. Save process state
pm2 save

echo "=== Deployment complete ==="

सामान्य नुकसान और समाधान

नुकसान 1: --update-env को भूल जाना

.env.local को अपडेट करने के बाद, --update-env के बिना pm2 restart all चलाने से पुराने पर्यावरण चर के साथ प्रक्रियाएं फिर से शुरू हो जाती हैं। हमेशा pm2 restart ecosystem.config.cjs --update-env का प्रयोग करें.

नुकसान 2: उत्पादन में watch: true का उपयोग करना

watch: true किसी फ़ाइल में परिवर्तन होने पर प्रक्रिया को पुनरारंभ करता है। उत्पादन में, बिल्ड आउटपुट हर परिनियोजन में बदलते हैं - यह अनंत पुनरारंभ लूप का कारण बनता है। हमेशा watch: false सेट करें.

नुकसान 3: सुंदर शटडाउन के लिए SIGTERM को संभालना नहीं

पुन: प्रारंभ/रोकने पर PM2 SIGTERM भेजता है। यदि आपका ऐप इसे संभाल नहीं पाता है, तो PM2 kill_timeout मिलीसेकंड प्रतीक्षा करता है और SIGKILL भेजता है - जिससे अनुरोध खो सकते हैं। NestJS में SIGTERM को संभालें:

// main.ts
const app = await NestFactory.create(AppModule);
await app.listen(3001);

// Graceful shutdown
process.on('SIGTERM', async () => {
  await app.close();
  process.exit(0);
});

नुकसान 4: PM2 लॉग डिस्क स्थान ख़त्म होना

pm2-logrotate के बिना, PM2 लॉग अनिश्चित काल तक बढ़ते हैं। भारी तस्करी वाली एपीआई प्रति दिन गीगाबाइट लॉग उत्पन्न कर सकती है। pm2-logrotate को तुरंत इंस्टॉल करें और उचित max_size (50MB) और retain (7 दिन) सेट करें।

नुकसान 5: रिबूट के बाद प्रक्रियाएँ खोना

pm2 start रिबूट के दौरान प्रक्रियाओं को जारी नहीं रखता है। आरंभिक सेटअप के बाद हमेशा pm2 startup + pm2 save चलाएँ। यदि रीबूट के बाद प्रक्रियाएं गायब हो जाती हैं, तो सहेजे गए डंप से पुनर्स्थापित करने के लिए pm2 resurrect चलाएँ।


अक्सर पूछे जाने वाले प्रश्न

मुझे क्लस्टर मोड बनाम फोर्क मोड का उपयोग कब करना चाहिए?

सीपीयू-बाउंड वर्कलोड (भारी गणना, डेटा प्रोसेसिंग के साथ नेस्टजेएस एपीआई) के लिए क्लस्टर मोड का उपयोग करें। क्लस्टर मोड instances कार्यकर्ता प्रक्रियाओं और उनके बीच PM2 लोड-संतुलन उत्पन्न करता है - सभी सीपीयू कोर का लाभ उठाता है। I/O-बाउंड वर्कलोड (नेक्स्ट.जेएस, स्टैटिक फाइल सर्विंग) के लिए फोर्क मोड का उपयोग करें या जब प्रक्रिया क्लस्टरिंग का समर्थन नहीं करती है (सिंगल-थ्रेडेड स्क्रिप्ट, डॉक्यूसॉरस सर्व)। Next.js अपने स्वयं के वर्कर थ्रेड को आंतरिक रूप से संभालता है, इसलिए instances: 1 के साथ फोर्क मोड सही है।

मैं डॉकर कंटेनर में PM2 कैसे चलाऊं?

डॉकर में PM2 संकेतों को सही ढंग से संभालने के लिए pm2 के बजाय pm2-docker (या pm2-runtime) का उपयोग करता है। रनटाइम संस्करण डिमोनाइज़ नहीं करता है (जिसके कारण डॉकर बाहर निकल जाएगा), चाइल्ड प्रक्रियाओं के लिए संकेतों को ठीक से अग्रेषित करता है, और फ़ाइलों के बजाय stdout/stderr पर लॉग करता है। अपने Dockerfile में CMD ["pm2-runtime", "ecosystem.config.cjs"] का उपयोग करें।

मैं किसी दूरस्थ मशीन से PM2 प्रक्रियाओं की निगरानी कैसे करूँ?

PM2 प्लस (भुगतान-प्रति-प्रक्रिया क्लाउड सेवा) एक वेब डैशबोर्ड प्रदान करता है। स्व-होस्ट की गई निगरानी के लिए, प्रोमेथियस निर्यातक के माध्यम से पीएम2 के मेट्रिक्स को उजागर करें और ग्राफाना में कल्पना करें। सरल स्थिति जांच के लिए, आप SSH कर सकते हैं और pm2 status चला सकते हैं, या HTTP एंडपॉइंट के माध्यम से मेट्रिक्स को उजागर कर सकते हैं जिसे आपका मॉनिटरिंग सिस्टम पोल करता है।

pm2 पुनः लोड और pm2 पुनरारंभ के बीच क्या अंतर है?

pm2 restart सभी श्रमिकों को एक साथ समाप्त कर देता है और उन्हें पुनः आरंभ करता है - एक संक्षिप्त अवधि होती है जिसमें कोई चालू श्रमिक नहीं होता (डाउनटाइम)। pm2 reload सुंदर है: यह नए श्रमिकों को शुरू करता है, उनके तैयार होने की प्रतीक्षा करता है, फिर पुराने श्रमिकों को बंद कर देता है - शून्य डाउनटाइम। उत्पादन परिनियोजन के लिए pm2 reload का उपयोग करें। नोट: रीलोड केवल क्लस्टर मोड में सही ढंग से काम करता है; फ़ोर्क मोड व्यवहार को पुनः आरंभ करने के लिए वापस आ जाता है।

मैं विभिन्न प्रक्रियाओं के लिए अलग-अलग पर्यावरण चर कैसे सेट करूं?

ecosystem.config.cjs में प्रत्येक प्रक्रिया के अपने env और env_production अनुभाग होते हैं। env_production अनुभाग का उपयोग तब किया जाता है जब आप --env production को PM2 कमांड पास करते हैं। रहस्यों के लिए, उन्हें कभी भी सीधे पारिस्थितिकी तंत्र फ़ाइल में न रखें - उन्हें सिस्टम वातावरण या .env.local फ़ाइल में सेट करें और PM2 को उन्हें प्राप्त करने दें। --update-env ध्वज यह सुनिश्चित करता है कि पुनरारंभ करते समय PM2 पर्यावरण चर को फिर से पढ़ता है।


अगले चरण

PM2 किसी भी उत्पादन Node.js परिनियोजन का एक मूलभूत हिस्सा है। ECOSIRE उत्पादन में 5 PM2 प्रक्रियाओं का प्रबंधन करता है - Next.js, NestJS, Docusaurus, और दो ब्रांड साइटें - मुख्य पर प्रत्येक पुश पर स्वचालित पुनरारंभ, लॉग रोटेशन और शून्य-डाउनटाइम तैनाती के साथ।

चाहे आपको DevOps इंजीनियरिंग समर्थन, उत्पादन परिनियोजन आर्किटेक्चर, या कंटेनरीकृत सेटअप में माइग्रेट करने में सहायता की आवश्यकता हो, हमारी सेवाओं का पता लगाएं यह देखने के लिए कि हम कैसे मदद कर सकते हैं।

शेयर करें:
E

लेखक

ECOSIRE Research and Development Team

ECOSIRE में एंटरप्राइज़-ग्रेड डिजिटल उत्पाद बना रहे हैं। Odoo एकीकरण, ई-कॉमर्स ऑटोमेशन, और AI-संचालित व्यावसायिक समाधानों पर अंतर्दृष्टि साझा कर रहे हैं।

WhatsApp पर चैट करें