您现在的位置是:网站首页 > 负载均衡与集群部署文章详情

负载均衡与集群部署

负载均衡与集群部署是提升Express应用性能和可靠性的关键手段。通过合理配置,可以有效分摊服务器压力,避免单点故障,确保应用在高并发场景下的稳定运行。

负载均衡的基本概念

负载均衡的核心思想是将网络请求分发到多个服务器节点,避免单个服务器过载。常见的负载均衡算法包括:

  1. 轮询(Round Robin):按顺序将请求分配给服务器
  2. 最少连接(Least Connections):将请求分配给当前连接数最少的服务器
  3. IP哈希(IP Hash):根据客户端IP地址分配服务器
// 简单的轮询负载均衡示例
const servers = ['http://server1:3000', 'http://server2:3000', 'http://server3:3000'];
let current = 0;

function getServer() {
  const server = servers[current];
  current = (current + 1) % servers.length;
  return server;
}

Express集群部署的实现方式

Node.js是单线程的,但可以通过集群模块充分利用多核CPU。Express应用可以通过以下方式实现集群:

使用Node.js原生cluster模块

const cluster = require('cluster');
const os = require('os');
const express = require('express');

if (cluster.isMaster) {
  const numCPUs = os.cpus().length;
  
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
  
  cluster.on('exit', (worker) => {
    console.log(`Worker ${worker.process.pid} died`);
    cluster.fork();
  });
} else {
  const app = express();
  
  app.get('/', (req, res) => {
    res.send(`Hello from worker ${process.pid}`);
  });
  
  app.listen(3000, () => {
    console.log(`Worker ${process.pid} started`);
  });
}

使用PM2进程管理器

PM2提供了更简单的集群管理方式:

pm2 start app.js -i max

负载均衡器的配置

Nginx配置示例

http {
  upstream express_servers {
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
    server 127.0.0.1:3002;
  }

  server {
    listen 80;
    
    location / {
      proxy_pass http://express_servers;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
    }
  }
}

HAProxy配置示例

frontend http-in
  bind *:80
  default_backend express_servers

backend express_servers
  balance roundrobin
  server server1 127.0.0.1:3000 check
  server server2 127.0.0.1:3001 check
  server server3 127.0.0.1:3002 check

会话保持与状态共享

在集群环境中,需要特别注意会话状态的管理:

使用Redis存储会话

const session = require('express-session');
const RedisStore = require('connect-redis')(session);

app.use(session({
  store: new RedisStore({
    host: 'redis-server',
    port: 6379
  }),
  secret: 'your-secret-key',
  resave: false,
  saveUninitialized: false
}));

使用JWT实现无状态认证

const jwt = require('jsonwebtoken');

app.post('/login', (req, res) => {
  // 验证用户凭证
  const token = jwt.sign({ userId: user.id }, 'secret-key', { expiresIn: '1h' });
  res.json({ token });
});

app.get('/protected', (req, res) => {
  const token = req.headers.authorization?.split(' ')[1];
  try {
    const decoded = jwt.verify(token, 'secret-key');
    res.send(`Hello user ${decoded.userId}`);
  } catch (err) {
    res.status(401).send('Invalid token');
  }
});

健康检查与故障转移

确保负载均衡器能够检测服务器状态:

Express健康检查端点

app.get('/health', (req, res) => {
  // 检查数据库连接等关键资源
  res.status(200).json({ status: 'healthy' });
});

Nginx健康检查配置

upstream express_servers {
  server 127.0.0.1:3000;
  server 127.0.0.1:3001 backup;
  
  check interval=3000 rise=2 fall=3 timeout=2000;
}

静态资源与缓存优化

在集群环境中优化静态资源服务:

使用CDN分发静态资源

app.use('/static', express.static('public', {
  maxAge: '1y',
  setHeaders: (res, path) => {
    if (path.endsWith('.css')) {
      res.setHeader('Content-Type', 'text/css');
    }
  }
}));

集群间的缓存同步

const NodeCache = require('node-cache');
const cache = new NodeCache({ stdTTL: 3600 });

// 使用Redis发布/订阅同步缓存
redisSubscriber.on('message', (channel, message) => {
  const { key, value } = JSON.parse(message);
  cache.set(key, value);
});

function setClusterCache(key, value) {
  cache.set(key, value);
  redisPublisher.publish('cache-update', JSON.stringify({ key, value }));
}

日志收集与监控

集中管理集群中各节点的日志:

使用Winston进行日志收集

const winston = require('winston');
const { Loggly } = require('winston-loggly-bulk');

const logger = winston.createLogger({
  transports: [
    new winston.transports.Console(),
    new Loggly({
      token: 'your-loggly-token',
      subdomain: 'your-subdomain',
      tags: ['express-cluster'],
      json: true
    })
  ]
});

app.use((req, res, next) => {
  logger.info(`${req.method} ${req.url}`);
  next();
});

使用Prometheus监控指标

const promBundle = require('express-prom-bundle');
const metricsMiddleware = promBundle({
  includeMethod: true,
  includePath: true,
  customLabels: { cluster_node: process.pid }
});

app.use(metricsMiddleware);

部署策略与蓝绿发布

实现零停机部署:

使用Nginx实现蓝绿部署

upstream blue {
  server 127.0.0.1:3000;
  server 127.0.0.1:3001;
}

upstream green {
  server 127.0.0.1:4000;
  server 127.0.0.1:4001;
}

# 通过变量切换流量
set $deployment "blue";

server {
  location / {
    if ($deployment = "blue") {
      proxy_pass http://blue;
    }
    if ($deployment = "green") {
      proxy_pass http://green;
    }
  }
}

使用Kubernetes进行滚动更新

apiVersion: apps/v1
kind: Deployment
metadata:
  name: express-app
spec:
  replicas: 4
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    spec:
      containers:
      - name: express
        image: your-image:v2
        ports:
        - containerPort: 3000
        readinessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 5
          periodSeconds: 5

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步