Nginx 反向代理与负载均衡实战——从入门到生产环境
Nginx 是目前最流行的 Web 服务器和反向代理软件,以高性能、低资源消耗、高稳定性著称。本文将带你从零开始,系统学习 Nginx 反向代理与负载均衡的核心概念、配置方法和生产环境最佳实践。
一、反向代理基础
1.1 什么是反向代理?
反向代理(Reverse Proxy)是一种代理服务器,它接收客户端的请求,然后将请求转发给后端的真实服务器,最后将服务器的响应返回给客户端。
与正向代理(VPN、翻墙代理)不同,反向代理是为服务器服务的,客户端不知道真实服务器的存在,只与反向代理服务器通信。
1.2 反向代理的作用
- 隐藏后端服务器:客户端只能看到反向代理服务器的 IP,提高安全性
- 负载均衡:将请求分发到多个后端服务器,提高系统吞吐量和可用性
- SSL 卸载:统一在反向代理层处理 HTTPS 加密解密,减轻后端服务器压力
- 静态文件缓存:直接返回静态资源,减少后端请求
- 统一入口:所有请求都经过反向代理,方便做访问控制、日志、限流等
1.3 Nginx vs Apache vs HAProxy
| 软件 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| Nginx | 高性能、低内存、支持反向代理和负载均衡 | 动态处理能力弱 | Web 服务器、反向代理、负载均衡 |
| Apache | 模块丰富、对动态页面支持好 | 内存占用高、并发性能一般 | 传统 Web 应用、需要复杂模块 |
| HAProxy | 专门的负载均衡器、性能极强 | 不支持静态文件服务 | 四层/七层负载均衡、高并发场景 |
对于绝大多数运维场景,Nginx 是最佳选择,它同时具备 Web 服务器、反向代理、负载均衡三种能力,配置简单,生态成熟。
二、基础反向代理配置
2.1 最简单的反向代理
server {
listen 80;
server_name app.yourdomain.com;
location / {
proxy_pass http://127.0.0.1:8080;
}
}这就是最简单的反向代理配置,所有访问 app.yourdomain.com 的请求都会被转发到本地 8080 端口的服务。
2.2 关键代理参数
生产环境中,我们还需要配置一些关键参数来保证代理的正确性和性能:
server {
listen 80;
server_name app.yourdomain.com;
location / {
# 后端服务地址
proxy_pass http://127.0.0.1:8080;
# 设置请求头,让后端能获取到真实客户端信息
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;
# 超时配置
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
# 缓冲配置,提高性能
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;
}
}参数说明:
proxy_set_header Host $host:保留原始请求的域名,否则后端拿到的是127.0.0.1:8080X-Real-IP:真实客户端 IPX-Forwarded-For:请求经过的所有代理 IP 链X-Forwarded-Proto:原始请求协议(HTTP/HTTPS)
2.3 路径重写
有时候需要对请求路径进行重写后再转发给后端:
location /api/ {
# 将 /api/xxx 重写为 /xxx 后转发
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://127.0.0.1:8080;
}或者使用 proxy_pass 的路径功能:
location /api/ {
# 注意末尾的 /,这会将 /api/xxx 转发为 http://backend/xxx
proxy_pass http://127.0.0.1:8080/;
}三、负载均衡配置
3.1 基础负载均衡
当后端有多个服务实例时,我们可以用 upstream 配置负载均衡:
# 定义后端服务器组
upstream myapp {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}
server {
listen 80;
server_name app.yourdomain.com;
location / {
proxy_pass http://myapp;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}默认使用轮询策略,每个请求按时间顺序逐一分配到不同的后端服务器。
3.2 负载均衡策略
Nginx 提供了多种负载均衡算法:
1. 轮询(默认)
upstream myapp {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}2. 加权轮询
按权重分配请求,权重越高分配的请求越多:
upstream myapp {
server 192.168.1.10:8080 weight=3; # 3/5 的请求
server 192.168.1.11:8080 weight=2; # 2/5 的请求
}3. IP 哈希(ip_hash)
按客户端 IP 分配,同一个客户端的请求始终转发到同一个后端服务器,解决 session 共享问题:
upstream myapp {
ip_hash;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}4. 最少连接(least_conn)
转发给当前连接数最少的后端服务器:
upstream myapp {
least_conn;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}5. 最短响应时间(fair)
按后端响应时间分配,需要安装第三方模块:
upstream myapp {
fair;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}3.3 健康检查
Nginx 内置了被动健康检查机制,当某台后端服务器出现问题时,会自动将其从负载均衡池中临时剔除:
upstream myapp {
server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.12:8080 backup; # 备用服务器,只有其他都挂了才用
}参数说明:
max_fails=3:允许 3 次请求失败fail_timeout=30s:30 秒内失败 3 次就暂停该服务器 30 秒backup:标记为备用服务器,只有其他所有服务器都不可用时才启用down:标记服务器永久下线
3.4 长连接配置
Nginx 和后端服务器之间使用长连接可以减少 TCP 握手开销,显著提升性能:
upstream myapp {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
keepalive 64; # 保持 64 个空闲长连接
}
server {
location / {
proxy_pass http://myapp;
proxy_set_header Connection ""; # 清除客户端 Connection 头
proxy_http_version 1.1; # 使用 HTTP/1.1 支持长连接
}
}四、高级反向代理技巧
4.1 静态文件分离
将静态文件直接由 Nginx 返回,动态请求转发给后端,这是最常见的性能优化手段:
server {
listen 80;
server_name www.yourdomain.com;
root /var/www/myapp;
# 静态文件直接由 Nginx 返回
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2)$ {
expires 30d; # 浏览器缓存 30 天
add_header Cache-Control "public, immutable";
}
# 动态请求转发给后端
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}4.2 基于路径的多服务代理
同一个域名下不同路径转发给不同的后端服务:
server {
listen 80;
server_name www.yourdomain.com;
location /api/ {
proxy_pass http://api-service/;
}
location /admin/ {
proxy_pass http://admin-service/;
}
location /static/ {
alias /var/www/static/;
}
location / {
proxy_pass http://frontend-service;
}
}4.3 基于域名的虚拟主机
同一个 Nginx 实例可以同时代理多个域名:
# 网站 A
server {
listen 80;
server_name www.site-a.com;
location / {
proxy_pass http://site-a-backend;
}
}
# 网站 B
server {
listen 80;
server_name www.site-b.com;
location / {
proxy_pass http://site-b-backend;
}
}4.4 WebSocket 代理
代理 WebSocket 需要特殊配置,因为 WebSocket 使用 Upgrade 头:
location /ws/ {
proxy_pass http://websocket-service;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400; # WebSocket 连接超时设为 1 天
}五、生产环境最佳实践
5.1 隐藏 Nginx 版本号
不要暴露具体的 Nginx 版本,减少被定向攻击的风险:
# 在 http 块中配置
http {
server_tokens off; # 隐藏版本号
# ...
}5.2 配置客户端上传大小限制
http {
client_max_body_size 100m; # 最大上传 100MB
# ...
}5.3 启用 Gzip 压缩
压缩响应内容,减少网络传输量,提升加载速度:
http {
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss;
# ...
}5.4 配置访问日志
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
# ...
}5.5 限流配置
防止恶意请求刷爆你的服务器:
http {
# 定义限流规则,按客户端 IP 限流,每秒最多 10 个请求
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
server {
location / {
# 应用限流规则,允许突发 5 个请求
limit_req zone=one burst=5 nodelay;
proxy_pass http://myapp;
}
}
}六、常见问题排查
6.1 502 Bad Gateway
- 后端服务挂了,检查后端服务是否正常运行
- 后端服务端口变了,检查
proxy_pass配置 - 防火墙阻止了 Nginx 和后端的通信
- 后端服务响应超时,调大
proxy_read_timeout
6.2 504 Gateway Timeout
- 后端服务处理太慢,优化后端性能
- 调大代理超时时间:
proxy_read_timeout 60s; - 后端发生了死锁或死循环
6.3 获取不到真实客户端 IP
- 检查是否配置了
proxy_set_header X-Real-IP $remote_addr; - 确认后端应用从
X-Real-IP或X-Forwarded-For头中获取 IP - 如果 Nginx 前面还有一层 CDN 或负载均衡,需要配置
real_ip_header
6.4 重定向地址变成内部地址
- 配置
proxy_redirect off;或者正确设置proxy_set_header Host $host; - 后端服务生成绝对地址时使用了错误的 Host 头
七、Nginx 配置调试技巧
7.1 验证配置文件
nginx -t # 只验证不重启
nginx -s reload # 验证通过后平滑重启7.2 查看 Nginx 版本和编译参数
nginx -V7.3 启用 debug 日志
# 在 server 或 location 块中配置
error_log /var/log/nginx/debug.log debug;7.4 返回调试信息
临时添加一个 location 返回 Nginx 变量值:
location /debug {
return 200 "host=$host remote_addr=$remote_addr proxy_add_x_forwarded_for=$proxy_add_x_forwarded_for";
}八、总结
Nginx 反向代理与负载均衡是现代 Web 架构的核心组件,掌握好它是每个运维工程师的必备技能。
核心要点回顾:
- 反向代理可以隐藏后端服务、统一入口、做 SSL 卸载和缓存
proxy_pass是最核心的代理指令,注意末尾/的区别- 必须配置
proxy_set_header传递真实客户端信息给后端 - upstream 支持轮询、加权、ip_hash、least_conn 等多种负载均衡策略
- 生产环境一定要配置健康检查、长连接、限流、日志
按照本文的配置方法,你可以快速搭建一套高性能、高可用的 Nginx 反向代理和负载均衡集群,支撑每秒数万甚至数十万的并发请求。
评论