Kodokon kodokon.com

प्रोडक्शन में जाना: प्रोसेस मैनेजर, Docker, cluster

प्रोडक्शन में भेजें: NODE_ENV, प्रोसेस मैनेजर, एक सही Docker इमेज, और cluster के साथ मल्टी-कोर स्केलिंग।

10 मिनट · 3 प्रश्न

इस पाठ को Kodokon में खोलें

NODE_ENV महज़ एक लाइब्रेरी परिपाटी है: Node का कोर इसे लगभग पूरी तरह अनदेखा करता है। लेकिन Express, समेत कई अन्य, इसका उपयोग व्यू को कैश करने और स्टैक ट्रेस छिपाने के लिए करते हैं; कुछ फ़्रेमवर्क NODE_ENV=production के साथ कई गुना तेज़ होते हैं। निर्भरताओं की ओर, npm ci --omit=dev ठीक lockfile को इंस्टॉल करता है, dev निर्भरताओं के बिना - npm install की तुलना में पुनरुत्पादनीय और तेज़। Node 20.6 से, --env-file किसी .env फ़ाइल को नेटिव रूप से, बिना किसी निर्भरता के, लोड करता है।

BASH
NODE_ENV=production node server.js

npm ci --omit=dev

node --env-file=.env server.js
प्रोडक्शन में जाने के लिए तीन बुनियादी कमांड।

एक Node प्रोसेस आख़िरकार हमेशा मर ही जाती है: मेमोरी की सीमा पार होना, बग, एक्सेप्शन। प्रोसेस मैनेजर की भूमिका इसे दोबारा शुरू करना है। दो विचारधाराएँ: किसी खाली मशीन पर, pm2 (या systemd) निगरानी करता है, दोबारा शुरू करता है, और बिना डाउनटाइम के रीलोड करता है; किसी कंटेनर में, यह भूमिका ऑर्केस्ट्रेटर (Kubernetes, ECS) निभाता है - प्रति कंटेनर एक प्रोसेस, और pm2 बेकार हो जाता है, हानिकारक तक, क्योंकि यह ऑर्केस्ट्रेटर से क्रैश छिपा देता है।

BASH
npm install -g pm2
pm2 start server.js -i max --name api
pm2 reload api
pm2 logs api --lines 100
pm2: -i max प्रति कोर एक वर्कर फ़ोर्क करता है, बिना डाउनटाइम के रीलोड।

Node के लिए विशिष्ट दो Docker जाल। एक: इमेज को बिना विशेषाधिकार वाले node उपयोगकर्ता के रूप में चलना चाहिए, जो आधिकारिक इमेज द्वारा प्रदान किया जाता है। दो: Node को PID 1 होने के लिए नहीं बनाया गया है - यह ज़ॉम्बी प्रोसेस को साफ़ नहीं करता; एक न्यूनतम init डालने के लिए कंटेनर को docker run --init (या Compose में init: true) के साथ लॉन्च करें। अंत में, CMD को exec रूप में लिखें: shell रूप /bin/sh डाल देता है, जो SIGTERM को आगे नहीं भेजता - पिछले पाठ का ग्रेसफुल शटडाउन कभी ट्रिगर ही नहीं होगा।

BASH
FROM node:20-slim AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev

FROM node:20-slim
ENV NODE_ENV=production
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
USER node
EXPOSE 3000
CMD ["node", "server.js"]
मल्टी-स्टेज Dockerfile: node उपयोगकर्ता, exec रूप में CMD।

एक अकेली Node प्रोसेस केवल एक कोर का उपयोग करती है। cluster मॉड्यूल प्रति कोर एक वर्कर प्रोसेस बनाता है: प्राइमरी पोर्ट पर सुनता है और कनेक्शन को वर्कर के बीच राउंड-रॉबिन में बाँटता है (यह डिफ़ॉल्ट व्यवहार है, Windows को छोड़कर)। हर वर्कर की अपनी मेमोरी और अपना इवेंट लूप होता है: कोई साझा अवस्था नहीं - सत्र और कैश को Redis या किसी समकक्ष में रहना चाहिए। शुद्ध गणना के लिए, worker_threads को प्राथमिकता दें, जो SharedArrayBuffer के ज़रिए मेमोरी साझा करता है।

JAVASCRIPT
import cluster from "node:cluster";
import { createServer } from "node:http";
import { availableParallelism } from "node:os";

if (cluster.isPrimary) {
  const count = availableParallelism();
  for (let i = 0; i < count; i += 1) cluster.fork();
  cluster.on("exit", (worker) => {
    console.log(`worker ${worker.process.pid} down`);
    cluster.fork();
  });
} else {
  createServer((req, res) => {
    res.end(`pid ${process.pid}`);
  }).listen(3000);
}
प्रति कोर एक वर्कर, मरने पर स्वतः दोबारा शुरू।

ज्ञान जांच

सुनिश्चित करें कि आपको इस पाठ के मुख्य बिंदु याद हैं।

  1. NODE_ENV=production वास्तव में क्या बदलता है?
    • Node.js एक अधिक आक्रामक JIT कंपाइलर सक्षम करता है
    • Express जैसी लाइब्रेरी अपने ऑप्टिमाइज़ेशन सक्षम करती हैं (व्यू कैशिंग, संक्षिप्त त्रुटियाँ)
    • Node.js HTTPS के बिना शुरू होने से मना कर देता है
  2. किसी Dockerfile में exec रूप CMD ["node", "server.js"] को प्राथमिकता क्यों दें?
    • exec रूप तेज़ी से शुरू होता है
    • exec रूप वेरिएबल इंटरपोलेशन की अनुमति देता है
    • shell रूप /bin/sh से होकर गुज़रता है, जो SIGTERM को Node प्रोसेस तक आगे नहीं भेजता
  3. cluster और 8 वर्कर के साथ, मेमोरी और एप्लिकेशन की अवस्था का क्या होता है?
    • हर वर्कर एक अलग प्रोसेस है: मेमोरी 8 गुना, कोई साझा अवस्था नहीं
    • वर्कर एक ही V8 heap साझा करते हैं
    • प्राइमरी समय-समय पर वर्कर के heap को मर्ज करता है