प्रोडक्शन में भेजें: NODE_ENV, प्रोसेस मैनेजर, एक सही Docker इमेज, और cluster के साथ मल्टी-कोर स्केलिंग।
इस पाठ को Kodokon में खोलेंNODE_ENV महज़ एक लाइब्रेरी परिपाटी है: Node का कोर इसे लगभग पूरी तरह अनदेखा करता है। लेकिन Express, समेत कई अन्य, इसका उपयोग व्यू को कैश करने और स्टैक ट्रेस छिपाने के लिए करते हैं; कुछ फ़्रेमवर्क NODE_ENV=production के साथ कई गुना तेज़ होते हैं। निर्भरताओं की ओर, npm ci --omit=dev ठीक lockfile को इंस्टॉल करता है, dev निर्भरताओं के बिना - npm install की तुलना में पुनरुत्पादनीय और तेज़। Node 20.6 से, --env-file किसी .env फ़ाइल को नेटिव रूप से, बिना किसी निर्भरता के, लोड करता है।
NODE_ENV=production node server.js
npm ci --omit=dev
node --env-file=.env server.jsएक Node प्रोसेस आख़िरकार हमेशा मर ही जाती है: मेमोरी की सीमा पार होना, बग, एक्सेप्शन। प्रोसेस मैनेजर की भूमिका इसे दोबारा शुरू करना है। दो विचारधाराएँ: किसी खाली मशीन पर, pm2 (या systemd) निगरानी करता है, दोबारा शुरू करता है, और बिना डाउनटाइम के रीलोड करता है; किसी कंटेनर में, यह भूमिका ऑर्केस्ट्रेटर (Kubernetes, ECS) निभाता है - प्रति कंटेनर एक प्रोसेस, और pm2 बेकार हो जाता है, हानिकारक तक, क्योंकि यह ऑर्केस्ट्रेटर से क्रैश छिपा देता है।
npm install -g pm2
pm2 start server.js -i max --name api
pm2 reload api
pm2 logs api --lines 100Node के लिए विशिष्ट दो Docker जाल। एक: इमेज को बिना विशेषाधिकार वाले node उपयोगकर्ता के रूप में चलना चाहिए, जो आधिकारिक इमेज द्वारा प्रदान किया जाता है। दो: Node को PID 1 होने के लिए नहीं बनाया गया है - यह ज़ॉम्बी प्रोसेस को साफ़ नहीं करता; एक न्यूनतम init डालने के लिए कंटेनर को docker run --init (या Compose में init: true) के साथ लॉन्च करें। अंत में, CMD को exec रूप में लिखें: shell रूप /bin/sh डाल देता है, जो SIGTERM को आगे नहीं भेजता - पिछले पाठ का ग्रेसफुल शटडाउन कभी ट्रिगर ही नहीं होगा।
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"]एक अकेली Node प्रोसेस केवल एक कोर का उपयोग करती है। cluster मॉड्यूल प्रति कोर एक वर्कर प्रोसेस बनाता है: प्राइमरी पोर्ट पर सुनता है और कनेक्शन को वर्कर के बीच राउंड-रॉबिन में बाँटता है (यह डिफ़ॉल्ट व्यवहार है, Windows को छोड़कर)। हर वर्कर की अपनी मेमोरी और अपना इवेंट लूप होता है: कोई साझा अवस्था नहीं - सत्र और कैश को Redis या किसी समकक्ष में रहना चाहिए। शुद्ध गणना के लिए, worker_threads को प्राथमिकता दें, जो SharedArrayBuffer के ज़रिए मेमोरी साझा करता है।
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);
}