2026年Node.js在CentOS上负载均衡完整配置指南:从Nginx到PM2集群(2026)

一、负载均衡基础认知

1.1 为什么需要负载均衡

Node.js是单线程模型,无法充分利用多核CPU。负载均衡可以:

收益类型 具体内容 说明
性能提升 充分利用多核CPU Node.js单进程只占用一个核
高可用性 故障自动转移 单点故障不影响服务
扩展性 水平扩展能力 增加服务器即可扩展
维护性 零停机部署 滚动重启不影响服务

1.2 负载均衡架构

## 典型负载均衡架构

客户端请求
    ↓
负载均衡器(Nginx/HAProxy)
    ↓
Node.js应用集群(多进程/多机器)
    ↓
数据库/缓存/外部API

1.3 Node.js负载均衡方案对比

方案 原理 优点 缺点 适用场景
Nginx反向代理 七层负载 功能丰富、SSL终止 配置复杂 生产环境推荐
PM2集群 进程管理+集群 简单、内置 单机器限制 单机多核
Docker+Swarm 容器编排 容器化部署 学习曲线陡 微服务架构
HAProxy 四层/七层负载 性能极高 功能较少 高性能场景

二、PM2集群模式配置

2.1 PM2安装与基本概念

# 安装PM2
sudo npm install -g pm2

# 启动应用(单进程)
pm2 start app.js --name "myapp"

# 查看状态
pm2 status

# 查看日志
pm2 logs myapp

# 重启应用
pm2 restart myapp

# 停止应用
pm2 stop myapp

# 删除应用
pm2 delete myapp

2.2 集群模式(推荐)

# 方法一:直接启动集群模式
pm2 start app.js -i max --name "myapp"
# -i max:根据CPU核心数启动对应数量的进程

# 方法二:指定进程数
pm2 start app.js -i 4 --name "myapp"
# 启动4个工作进程

# 方法三:使用配置文件
// ecosystem.config.js
module.exports = {
  apps: [{
    name: "myapp",
    script: "app.js",
    instances: "max",      // 根据CPU核心数
    exec_mode: "cluster",  // 集群模式
    watch: false,
    autorestart: true,
    max_memory_restart: "500M",
    env: {
      NODE_ENV: "development"
    },
    env_production: {
      NODE_ENV: "production"
    }
  }]
}
# 使用配置文件启动
pm2 start ecosystem.config.js --env production

# 查看集群状态
pm2 status

# 调整进程数(扩容/缩容)
pm2 scale myapp +2   # 增加2个进程
pm2 scale myapp 8     # 调整为8个进程
pm2 scale myapp -2   # 减少2个进程

2.3 PM2集群优化

// app.js - 确保应用支持集群模式

const http = require('http');
const cluster = require('cluster');
const numCPUs = require('os').cpus().length;

// 方法一:手动使用cluster模块
if (cluster.isMaster) {
  console.log(`主进程 ${process.pid} 正在运行`);

  // 衍生工作进程
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`工作进程 ${worker.process.pid} 已退出`);
    // 自动重启
    cluster.fork();
  });
} else {
  // 工作进程共享同一个TCP连接
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('Hello World\n');
  }).listen(8000);

  console.log(`工作进程 ${process.pid} 已启动`);
}
# 方法二:使用PM2管理(更推荐)
pm2 start app.js -i max --name "myapp"

# 监控集群
pm2 monit

# 查看详细状态
pm2 show myapp

2.4 PM2开机启动

# 生成开机启动脚本
pm2 startup

# 保存当前进程列表
pm2 save

# 恢复进程列表
pm2 resurrect

# 查看启动配置
pm2 list

三、Nginx负载均衡配置

3.1 安装Nginx

# CentOS 7
sudo yum install -y epel-release
sudo yum install -y nginx

# CentOS 8/Stream
sudo dnf install -y nginx

# 启动Nginx
sudo systemctl start nginx
sudo systemctl enable nginx

# 验证
curl http://127.0.0.1

3.2 配置Upstream负载均衡

# /etc/nginx/conf.d/nodejs-upstream.conf

# 定义上游服务器集群
upstream nodejs_cluster {
    # 负载均衡算法
    # 1. 轮询(默认)
    # 2. 加权轮询
    # 3. IP哈希(会话保持)
    # 4. 最少连接

    # 轮询(默认)
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
    server 127.0.0.1:3002;
    server 127.0.0.1:3003;

    # 加权轮询
    # server 127.0.0.1:3000 weight=3;
    # server 127.0.0.1:3001 weight=1;

    # IP哈希(会话保持)
    # ip_hash;

    # 最少连接
    # least_conn;

    # 健康检查(需要nginx-plus或第三方模块)
    # max_fails=3 fail_timeout=30s;
}

# 虚拟主机配置
server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://nodejs_cluster;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # 超时设置
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

3.3 启动多个Node.js实例

# 使用PM2启动多个端口实例
pm2 start app.js --name "app-3000" -i 1 -- -p 3000
pm2 start app.js --name "app-3001" -i 1 -- -p 3001
pm2 start app.js --name "app-3002" -i 1 -- -p 3002
pm2 start app.js --name "app-3003" -i 1 -- -p 3003
// app.js - 支持从命令行参数读取端口
const http = require('http');
const port = process.env.PORT || process.argv[2] || 3000;

http.createServer((req, res) => {
  res.writeHead(200);
  res.end(`Hello from port ${port}\n`);
}).listen(port, () => {
  console.log(`Server running on port ${port}`);
});

3.4 Nginx负载均衡算法详解

# 1. 轮询(Round Robin)- 默认
upstream backend {
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
}
# 每个请求按时间顺序逐一分配到不同后端服务器

# 2. 加权轮询(Weighted Round Robin)
upstream backend {
    server 127.0.0.1:3000 weight=3;
    server 127.0.0.1:3001 weight=1;
}
# 权重越高,被分配到的概率越大

# 3. IP哈希(IP Hash)- 会话保持
upstream backend {
    ip_hash;
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
}
# 同一IP客户端总是访问同一后端服务器

# 4. 最少连接(Least Connections)
upstream backend {
    least_conn;
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
}
# 请求分配到当前活动连接数最少的服务器

# 5. 通用哈希(Generic Hash)
upstream backend {
    hash $request_uri consistent;
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
}
# 根据指定键(如URI)分配,支持一致性哈希

3.5 健康检查配置

# 主动健康检查(需要nginx-plus或开源版本打补丁)
upstream backend {
    server 127.0.0.1:3000 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:3001 max_fails=3 fail_timeout=30s;
}

server {
    location / {
        proxy_pass http://backend;
        # 健康检查失败重试
        proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
        proxy_next_upstream_tries 3;
        proxy_next_upstream_timeout 30s;
    }

    # 健康检查端点
    location /health {
        access_log off;
        return 200 "OK";
    }
}

四、多机负载均衡配置

4.1 架构设计

## 多机负载均衡架构

                Internet
                    ↓
            DNS负载均衡(可选)
                    ↓
            Nginx负载均衡器(主)
                    ↓
        -------------------------
        ↓          ↓          ↓
    Node.js    Node.js    Node.js
    服务器A    服务器B    服务器C
        ↓          ↓          ↓
        -------------------------
                    ↓
            共享数据库/Redis

4.2 Nginx配置多后端

# /etc/nginx/conf.d/nodejs-multi.conf

upstream nodejs_cluster {
    # 多机后端
    server 192.168.1.101:3000 weight=2 max_fails=3 fail_timeout=30s;
    server 192.168.1.102:3000 weight=2 max_fails=3 fail_timeout=30s;
    server 192.168.1.103:3000 weight=1 max_fails=3 fail_timeout=30s;

    # 备用服务器
    server 192.168.1.104:3000 backup;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://nodejs_cluster;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # 跨机器负载均衡优化
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

4.3 多机部署脚本

#!/bin/bash
# Node.js多机部署脚本

# 定义服务器列表
SERVERS=("192.168.1.101" "192.168.1.102" "192.168.1.103")
APP_DIR="/opt/myapp"
APP_PORT=3000

for SERVER in "${SERVERS[@]}"; do
    echo "部署到服务器: $SERVER"

    # 1. 同步代码
    rsync -avz --delete ./ $SERVER:$APP_DIR/

    # 2. 安装依赖
    ssh $SERVER "cd $APP_DIR && npm install --production"

    # 3. 重启应用
    ssh $SERVER "pm2 restart myapp || pm2 start $APP_DIR/app.js --name myapp -i max"

    # 4. 验证
    ssh $SERVER "pm2 status"
done

echo "===== 部署完成 ====="

4.4 高可用Nginx配置

# 主Nginx:/etc/nginx/nginx.conf
upstream nodejs_backend {
    ip_hash;  # 会话保持
    server 192.168.1.101:3000;
    server 192.168.1.102:3000;
    server 192.168.1.103:3000;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://nodejs_backend;
        # ... 其他代理配置
    }
}
# 配置Keepalived实现Nginx高可用

# 安装Keepalived
sudo yum install -y keepalived

# 主节点配置:/etc/keepalived/keepalived.conf
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1

    authentication {
        auth_type PASS
        auth_pass 1111
    }

    virtual_ipaddress {
        192.168.1.100/24  # 虚拟IP(VIP)
    }
}

# 备节点配置
vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 50  # 优先级低于主节点
    # ... 其他配置相同
}

五、Docker容器化负载均衡

5.1 Docker Compose配置

# docker-compose.yml

version: '3.8'

services:
  # Node.js应用(多副本)
  app:
    build: .
    deploy:
      replicas: 4  # 启动4个副本
    environment:
      - NODE_ENV=production
    networks:
      - app-network

  # Nginx负载均衡器
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - app
    networks:
      - app-network

networks:
  app-network:
    driver: overlay  # 用于跨主机通信
# nginx.conf - Docker环境下的负载均衡

upstream nodejs {
    server app:3000;
}

server {
    listen 80;

    location / {
        proxy_pass http://nodejs;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

5.2 Docker Swarm模式

# 初始化Swarm集群
docker swarm init --advertise-addr 192.168.1.100

# 其他节点加入集群
docker swarm join --token <token> 192.168.1.100:2377

# 部署服务(带负载均衡)
docker service create --name myapp \
    --replicas 4 \
    --publish 3000:3000 \
    myapp:latest

# 查看服务
docker service ls
docker service ps myapp

# 扩容/缩容
docker service scale myapp=8

# 更新服务(滚动更新)
docker service update --image myapp:v2 myapp

六、性能优化

6.1 Node.js应用优化

// 1. 使用集群模式
const cluster = require('cluster');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  // 工作进程
  const express = require('express');
  const app = express();
  const port = process.env.PORT || 3000;

  // 2. 使用gzip压缩
  const compression = require('compression');
  app.use(compression());

  // 3. 使用连接池
  const mysql = require('mysql2/promise');
  const pool = mysql.createPool({
    host: 'localhost',
    user: 'root',
    password: 'password',
    database: 'myapp',
    connectionLimit: 10,  // 根据负载均衡节点数调整
    queueLimit: 0
  });

  // 4. 缓存热点数据
  const redis = require('redis');
  const client = redis.createClient();

  app.get('/api/data', async (req, res) => {
    // 先查缓存
    const cached = await client.get('hot-data');
    if (cached) {
      return res.json(JSON.parse(cached));
    }

    // 查数据库
    const [rows] = await pool.query('SELECT * FROM hot_table LIMIT 100');
    await client.setex('hot-data', 300, JSON.stringify(rows));
    res.json(rows);
  });

  app.listen(port);
}

6.2 Nginx优化

# /etc/nginx/nginx.conf - 优化参数

# 工作进程数(通常等于CPU核心数)
worker_processes auto;

# 每个工作进程的最大连接数
events {
    worker_connections 10240;
    use epoll;  # Linux高性能事件模型
    multi_accept on;
}

http {
    # 文件描述符缓存
    open_file_cache max=10000 inactive=30s;
    open_file_cache_valid 60s;
    open_file_cache_min_uses 2;

    # 缓冲区优化
    client_body_buffer_size 128k;
    client_max_body_size 10m;
    client_header_buffer_size 1k;

    # TCP优化
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 100;

    # Gzip压缩
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css application/json application/javascript;

    # 代理优化
    proxy_buffering off;
    proxy_buffer_size 16k;
    proxy_busy_buffers_size 24k;
    proxy_buffers 64 4k;

    # 上游服务器配置
    upstream backend {
        keepalive 32;  # 保持连接池
        server 127.0.0.1:3000;
        server 127.0.0.1:3001;
    }

    server {
        location / {
            proxy_pass http://backend;
            # 启用连接复用
            proxy_http_version 1.1;
            proxy_set_header Connection "";
        }
    }
}

七、监控与维护

7.1 PM2监控

# 实时监控
pm2 monit

# 查看详细信息
pm2 show myapp

# 查看日志
pm2 logs myapp --lines 100

# 清理日志
pm2 flush

# 安装PM2 Plus(商业监控)
pm2 plus

7.2 Nginx日志分析

# 访问日志分析
tail -f /var/log/nginx/access.log

# 统计QPS
watch -n 1 "wc -l /var/log/nginx/access.log | awk '{print \$1 \" requests\"}"

# 统计状态码
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

# 统计最频繁访问的URL
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# 统计最慢的请求
awk '{print $NF " " $7}' /var/log/nginx/access.log | sed 's/"//g' | sort -rn | head -20

7.3 完整监控脚本

#!/bin/bash
# Node.js负载均衡监控脚本

# 1. 检查Node.js进程
check_node_processes() {
    echo "===== Node.js进程状态 ====="
    pm2 status
    echo ""
}

# 2. 检查Nginx状态
check_nginx() {
    echo "===== Nginx状态 ====="
    systemctl status nginx --no-pager | grep Active
    echo "Nginx连接数: $(netstat -an | grep :80 | wc -l)"
    echo ""
}

# 3. 检查负载均衡后端
check_upstream() {
    echo "===== 上游服务器状态 ====="
    for port in 3000 3001 3002 3003; do
        if curl -s http://127.0.0.1:$port/health > /dev/null; then
            echo "端口 $port: ✅ 正常"
        else
            echo "端口 $port: ❌ 不可用"
        fi
    done
    echo ""
}

# 4. 检查系统资源
check_system() {
    echo "===== 系统资源 ====="
    echo "CPU使用率: $(top -bn1 | grep "Cpu(s)" | awk '{print $2}')"
    echo "内存使用: $(free -h | grep Mem | awk '{print $3 "/" $2}')"
    echo "磁盘使用: $(df -h / | tail -1 | awk '{print $5}')"
    echo ""
}

# 5. 检查网络连接
check_network() {
    echo "===== 网络连接 ====="
    echo "ESTABLISHED连接数: $(netstat -an | grep ESTABLISHED | wc -l)"
    echo "TIME_WAIT连接数: $(netstat -an | grep TIME_WAIT | wc -l)"
    echo ""
}

# 执行所有检查
check_node_processes
check_nginx
check_upstream
check_system
check_network

# 6. 性能测试(可选)
echo "===== 性能测试(10秒)====="
ab -n 1000 -c 100 http://127.0.0.1/ || echo "请安装apache2-utils: sudo yum install -y httpd-tools"

八、常见问题与解决方案

Q1:负载均衡后会话(Session)丢失怎么办?

// 解决方案一:使用Redis存储Session
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
const redis = require('redis');

const redisClient = redis.createClient({
    host: '127.0.0.1',
    port: 6379
});

app.use(session({
    store: new RedisStore({ client: redisClient }),
    secret: 'your-secret',
    resave: false,
    saveUninitialized: false,
    cookie: { secure: false }
}));
# 解决方案二:使用IP哈希保持会话
upstream backend {
    ip_hash;
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
}

Q2:如何平滑重启(零停机)?

# PM2零停机重启
pm2 reload myapp

# 或逐个重启(更精细控制)
pm2 restart myapp --only app-3000
sleep 5
pm2 restart myapp --only app-3001
# ...

# Nginx平滑重载配置
sudo nginx -t && sudo systemctl reload nginx

Q3:如何排查负载不均衡?

# 1. 查看Nginx访问日志,分析请求分布
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c

# 2. 检查上游服务器权重配置
grep "server.*weight" /etc/nginx/conf.d/*.conf

# 3. 检查服务器负载
for port in 3000 3001 3002 3003; do
    echo "Port $port CPU使用率:"
    top -b -n1 -p $(pgrep -f "port $port") | grep node
done

九、总结

Node.js在CentOS上实现负载均衡的完整方案:

  1. 单机多核:使用PM2集群模式
  2. 多机负载:使用Nginx反向代理
  3. 容器化:使用Docker Compose或Swarm
  4. 高可用:配置Keepalived+Nginx主备
  5. 监控维护:使用PM2 monit+Nginx日志分析
# 快速启动命令汇总

# 1. PM2集群模式
pm2 start app.js -i max --name "myapp"

# 2. Nginx负载均衡
sudo systemctl start nginx

# 3. 查看状态
pm2 status && systemctl status nginx

# 4. 监控
pm2 monit

注:本文基于Node.js 20.x和Nginx 1.24编写,具体配置可能因版本而异。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注