Skip to content

Nginx 负载均衡

负载均衡(Load Balancing)是分布式系统中的核心技术,它通过将网络流量合理分配到多个服务器,实现资源优化、吞吐量提升和容错能力增强。当系统面临大量用户访问,负载过高的时候,通常会使用Nginx增加服务器数量来进行横向扩展,然后将请求分发到各个服务器上。

Nginx作为负载均衡解决方案具有以下显著优势:

  • 高性能事件驱动架构:基于epoll/kqueue的异步非阻塞模型,能够处理数百万并发连接
  • 灵活的负载算法:支持轮询、加权轮询、IP哈希、最少连接等多种内置分发策略
  • 动态配置能力:支持运行时上游服务器组更新,无需重启服务
  • 健康检查机制:通过被动或主动方式自动屏蔽故障节点,提高系统可靠性
  • 协议支持广泛:可实现HTTP、HTTPS、TCP和UDP等多种协议的负载均衡

基本配置结构

Nginx负载均衡配置主要涉及两个核心模块:upstreamserverupstream模块用于定义后端服务器组,而server模块中的location配置则通过proxy_pass指令将请求转发到上游服务器组。

nginx
http {
    upstream backend {
        # 默认轮询策略
        server 192.168.1.101:8080;
        server 192.168.1.102:8080;
        server 192.168.1.103:8080;
    }
    
    server {
        listen 80;
        
        location / {
            proxy_pass http://backend;
            proxy_set_header Host $host;
        }
    }
}
  • proxy_pass:核心指令,用于将请求转发到上游服务器组,值是upstream定义的名称
  • proxy_set_header:修改转发给后端服务器的请求头,常见设置包括:
    • Host $host:保留原始请求的主机头
    • X-Real-IP $remote_addr:传递客户端真实IP
    • X-Forwarded-For $proxy_add_x_forwarded_for:记录请求经过的代理服务器链
  • upstream:定义后端服务器池,支持多种参数:
  • server:后端服务器地址,格式为host:port
    • weight:权重值,用于加权轮询
    • max_fails和fail_timeout:健康检查相关参数

负载均衡算法

轮询算法(Round Robin)

原理:默认算法,请求按时间顺序均匀分配到各个服务器。

配置示例

nginx
upstream backend {
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
}

特点

  • 优点:简单公平,适用于后端服务器性能相近的场景
  • 缺点:不考虑服务器实际负载,性能差异大时可能导致负载不均

适用场景:后端服务器配置相同且无状态服务的简单应用

加权轮询(Weighted Round Robin)

原理:在轮询基础上,根据服务器性能分配权重,权重高的服务器接收更多请。

配置示例

nginx
upstream backend {
    server 192.168.1.101:8080 weight=3; # 60%流量
    server 192.168.1.102:8080 weight=2; # 40%流量
}

特点

  • 优点:根据服务器实际性能合理分配请求,提高资源利用率
  • 缺点:静态权重,无法适应服务器负载的动态变化

适用场景:服务器性能不均(如CPU/内存差异)的环境

IP哈希(IP Hash)

原理:根据客户端IP计算哈希值,相同IP的请求固定分配到同一台服务器。

配置示例

nginx
upstream backend {
    ip_hash;
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
}

特点

  • 优点:解决会话保持问题,避免用户在不同服务器间切换导致的会话丢失
  • 缺点:在客户端使用NAT或大量请求来自同一IP时会导致负载不均

适用场景:需要会话保持的应用(如购物车、登录状态)

最少连接(Least Connections)

原理:将请求优先分配给当前连接数最少的服务器。

配置示例

nginx
upstream backend {
    least_conn;
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
}

特点

  • 优点:考虑服务器实际负载,使负载分配更加均衡
  • 缺点:计算开销略大于简单轮询

适用场景:长连接服务(如WebSocket、数据库连接池)

随机算法 (Random)

原理:随机选择后端服务器

nginx
upstream backend {
    random;
    server backend1.example.com;
    server backend2.example.com;
}

URI哈希(URI Hash)

原理:根据请求URI分配流量,相同URI始终到同一服务器。

配置示例

nginx
upstream backend {
    hash $request_uri consistent;
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
}

特点

  • 优点:提高缓存命中率,优化资源使用
  • 缺点:需要安装第三方模块(ngx_http_upstream_hash_module)

适用场景:缓存优化(如CDN边缘节点)

fair

比 weight、ip_hash更加智能的负载均衡算法,fair算法可以根据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间 来分配请求,响应时间短的优先分配。

fair是Nginx的一个第三方负载均衡算法,不是Nginx官方自带的模块,需要通过第三方模块nginx-upstream-fair来实现

安装

bash
# 下载模块
git clone https://github.com/gnosek/nginx-upstream-fair.git

# 编译Nginx时添加模块
./configure --add-module=/path/to/nginx-upstream-fair
make && make install

配置

nginx
upstream backend {
    fair;
    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com;
}

特点

  • 优点:更智能的负载分配,避免服务器过载自动适应后端服务器性能变化

  • 缺点:需要额外安装第三方模块,相比简单算法有轻微性能开销

算法选择决策指南

  1. 无状态服务:轮询或加权轮询(服务器性能不一时)
  2. 会话保持需求:IP哈希或Cookie绑定
  3. 长连接服务:最少连接算法
  4. 缓存优化:URI哈希或通用哈希
  5. 动态负载适应:商业版Nginx Plus的基于响应时间算法

负载均衡代理参数

nginx
server {
    ...
    upstream example.com {
    	server 192.168.10.1:8080;    
    }
    server {
        proxy_pass http://example.com;
        # 可引入支持的代理参数
    	include proxy.conf;    
    }    
    ...
}

核心代理指令

  • proxy_pass

    nginx
    proxy_pass http://backend_server;
    • 定义后端服务器地址,可以是域名、IP或upstream名称
    • 注意:URL结尾是否带/会影响URI传递方式
  • proxy_set_header

    nginx
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    • 修改转发给后端服务器的请求头
    • 生产环境必须设置的关键头:
      • Host:保留原始请求的主机名
      • X-Real-IP:传递客户端真实IP
      • X-Forwarded-For:记录请求经过的代理链

连接控制参数

  • proxy_connect_timeout

    nginx
    proxy_connect_timeout 5s;
    • 与后端服务器建立连接的超时时间
    • 生产建议:3-10秒,根据网络状况调整
  • proxy_send_timeout

    nginx
    proxy_send_timeout 15s;
    • 发送请求到后端服务器的超时时间
    • 生产建议:10-30秒,取决于请求大小
  • proxy_read_timeout

    nginx
    proxy_read_timeout 30s;
    • 从后端服务器读取响应的超时时间
    • 生产建议:30-60秒,API服务可适当缩短

缓冲区配置

  • proxy_buffer_size

    nginx
    proxy_buffer_size 4k;
    • 设置从后端服务器读取的第一部分响应缓冲区大小
    • 通常包含响应头
  • proxy_buffers

    nginx
    proxy_buffers 8 16k;
    • 设置用于读取响应的缓冲区数量和大小
    • 格式:数量 大小
    • 生产建议:8-16 16k-32k,根据平均响应大小调整
  • proxy_busy_buffers_size

    nginx
    proxy_busy_buffers_size 32k;
    • 当缓冲区满时,限制可以标记为"busy"的缓冲区大小
    • 通常设置为proxy_buffers中单个缓冲区大小的2倍

连接复用

  • proxy_http_version

    nginx
    proxy_http_version 1.1;
    • 与后端服务器通信使用的HTTP协议版本
    • 必须1.1才能启用keepalive
  • proxy_set_header Connection

    nginx
    proxy_set_header Connection "";
    • 清空Connection头,启用keepalive
  • upstream keepalive

    nginx
    upstream backend {
        server 10.0.0.1:8080;
        keepalive 32;
    }
    • 保持到后端服务器的长连接数量
    • 生产建议:根据并发量设置32-256

请求头控制

  • proxy_hide_header

    nginx
    proxy_hide_header X-Powered-By;
    • 隐藏后端服务器返回的特定响应头
    • 常用于隐藏服务器信息,增强安全性
  • proxy_pass_header

    nginx
    proxy_pass_header Server;
    • 允许传递后端服务器设置的特定响应头

重定向处理

  • proxy_redirect:

    nginx
    proxy_redirect off;
    proxy_redirect http://backend https://frontend;
    • 修改后端返回的重定向Location头
    • 生产环境建议:关闭或正确配置避免重定向到内网地址

缓存控制

  • proxy_cache:

    proxy_cache my_cache;
    proxy_cache_key "$scheme$request_method$host$request_uri";
    proxy_cache_valid 200 302 10m;
    • 启用响应缓存,显著减轻后端负载
    • 需要配合proxy_cache_path指令使用

大文件处理

  • proxy_max_temp_file_size

    nginx
    proxy_max_temp_file_size 1024m;
    • 当响应体超出缓冲区时,允许使用的临时文件最大大小
    • 0表示禁用临时文件
  • proxy_temp_file_write_size

    nginx
    proxy_temp_file_write_size 32k;
    • 写入临时文件时每次写入的数据量

负载均衡容错

  • proxy_next_upstream

    nginx
    proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
    • 定义在什么情况下请求应转发到下一个服务器
    • 生产建议:包含error、timeout和5xx状态码
  • proxy_next_upstream_tries

    nginx
    proxy_next_upstream_tries 3;
    • 尝试转发到下一个服务器的最大次数

健康检查机制

健康检查是生产环境中必不可少的配置,它能够自动屏蔽故障节点,确保系统的高可用性

被动健康检查

nginx
upstream backend {
    server 192.168.1.101:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.102:8080 max_fails=3 fail_timeout=30s;
}
  • max_fails:在fail_timeout时间内失败达到此次数,标记服务器不可用
  • fail_timeout:既是失败计数的时间窗口,也是服务器被标记为不可用的持续时间

工作原理

  1. 当请求失败(连接超时或返回5xx错误),失败计数器+1
  2. fail_timeout时间窗口内累计失败达到max_fails,标记服务器不可用
  3. 经过fail_timeout时间后,Nginx会尝试恢复该服务器

主动健康检查

需Nginx Plus或第三方模块

nginx
upstream backend {
    zone backend 64k;
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
    health_check interval=5s fails=3 passes=2 uri=/health;
}
  • 定期发送探测请求验证服务器状态
  • 更及时地发现故障节点

负载均衡优化

会话保持方案

Cookie绑定

nginx
upstream backend {
    sticky cookie srv_id expires=1h domain=.example.com path=/;
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
}
  • 通过注入Cookie实现会话保持
  • 比IP哈希更适用于客户端使用NAT的环境

SSL/TLS

nginx
server {
    listen 443 ssl;
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    location / {
        proxy_pass http://backend;
        proxy_set_header X-Forwarded-Proto https;
    }
}
  • 前端HTTPS,后端HTTP
  • 通过X-Forwarded-Proto头告知后端原始协议

连接池配置

nginx
upstream backend {
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
    keepalive 32; # 保持的长连接数量
}
server {
    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}
  • 减少TCP连接建立的开销
  • 提高高并发下的性能