1. Cluster Module
import cluster from 'node:cluster'
import { createServer } from 'node:http'
import os from 'node:os'
const numCPUs = os.cpus().length
if (cluster.isPrimary) {
console.log(`Primary ${process.pid} is running`)
// Fork workers
for (let i = 0; i < numCPUs; i++) {
cluster.fork()
}
cluster.on('exit', (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} died (${signal || code})`)
cluster.fork() // Auto-restart
})
} else {
const server = createServer((req, res) => {
res.writeHead(200)
res.end(`Worker ${process.pid}\n`)
})
server.listen(3000)
console.log(`Worker ${process.pid} started`)
}
2. Graceful Shutdown
if (cluster.isPrimary) {
function shutdown() {
console.log('Shutting down cluster...')
for (const id in cluster.workers) {
cluster.workers[id]?.send('shutdown')
}
setTimeout(() => process.exit(0), 10000) // Force exit after 10s
}
process.on('SIGTERM', shutdown)
process.on('SIGINT', shutdown)
} else {
const server = createServer(handler)
server.listen(3000)
process.on('message', (msg) => {
if (msg === 'shutdown') {
server.close(() => {
console.log(`Worker ${process.pid} closed gracefully`)
process.exit(0)
})
}
})
}
3. PM2 Process Manager
// ecosystem.config.cjs
module.exports = {
apps: [{
name: 'api-server',
script: 'dist/app.js',
instances: 'max', // Số CPU cores
exec_mode: 'cluster',
max_memory_restart: '1G',
env_production: {
NODE_ENV: 'production',
PORT: 3000,
},
// Logs
error_file: 'logs/err.log',
out_file: 'logs/out.log',
merge_logs: true,
log_date_format: 'YYYY-MM-DD HH:mm:ss',
}],
}
# PM2 commands
pm2 start ecosystem.config.cjs --env production
pm2 reload api-server # Zero-downtime reload
pm2 scale api-server +2 # Thêm 2 instances
pm2 monit # Monitor dashboard
pm2 logs api-server --lines 50
pm2 save && pm2 startup # Auto-start on boot
4. Zero-Downtime Deployment
#!/bin/bash
# deploy.sh
git pull origin main
pnpm install --frozen-lockfile
pnpm build
pm2 reload ecosystem.config.cjs --env production
# PM2 reload từng worker 1, đảm bảo luôn có worker handling requests
5. Sticky Sessions
// Khi dùng WebSocket hoặc session, cần sticky sessions
// Dùng nginx upstream hoặc PM2 sticky cluster
// Với nginx:
// upstream app {
// ip_hash; # Sticky sessions
// server 127.0.0.1:3001;
// server 127.0.0.1:3002;
// }
Bài tiếp theo: TCP, UDP & WebSockets — net, dgram, ws.