Nginx 反向代理与负载均衡实战指南
Nginx 是 Web 架构中的"万能胶水":反向代理、负载均衡、静态资源、HTTPS、限流、缓存、灰度发布,一个它全包了。本文从安装配置讲起,覆盖反向代理、负载均衡、动静分离、HTTPS、限流、常见坑,全程带配置,可直接抄。
一、Nginx 是什么
1.1 三种典型角色
Web 服务器:托管静态资源(HTML、JS、图片)------比 Tomcat 快几个数量级。
反向代理:接收外部请求,转发给内部后端(Tomcat、Spring Boot)。
用户 → Nginx(80) → 后端应用(8080)
负载均衡:多个后端实例,Nginx 按策略分发。
用户 → Nginx(80) → app1:8080
→ app2:8080
→ app3:8080
1.2 为什么用 Nginx
- 高并发:事件驱动,单机 5-10 万并发(Apache 同期只有几千);
- 稳定:内存占用小、久跑不掉;
- 灵活:配置热加载(reload 不中断服务);
- 生态:HTTP/2、HTTPS、WebSocket、限流、缓存全套。
二、安装与基本配置
2.1 安装
bash
# CentOS
yum install -y nginx
# Ubuntu
apt install -y nginx
# 或编译安装(要自定义模块时)
Docker 方式:
bash
docker run -d --name nginx -p 80:80 -v /data/nginx:/etc/nginx nginx:1.25
2.2 配置文件结构
/etc/nginx/
├── nginx.conf # 主配置
├── conf.d/ # 子配置(include)
└── sites-enabled/ # 站点配置
nginx
# nginx.conf 主结构
user nginx;
worker_processes auto; # 和 CPU 核数一致
events {
worker_connections 10240; # 每个 worker 最大连接数
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 引入站点配置(推荐把每个站点写一个文件)
include /etc/nginx/conf.d/*.conf;
}
2.3 基本命令
bash
nginx -t # 测试配置语法(改完必跑)
nginx -s reload # 热加载(不中断)
nginx -s stop # 停止
systemctl start nginx # 启动服务
systemctl status nginx
红线 :改配置先 nginx -t,通过再 reload。
三、反向代理配置
3.1 最简单代理
nginx
server {
listen 80;
server_name api.example.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_pass:后端地址;- 三个
proxy_set_header:必须,否则后端拿不到真实 IP; $host:请求的域名;$remote_addr:客户端 IP。
3.2 按路径分发(网关雏形)
nginx
server {
listen 80;
server_name mall.example.com;
location /api/user/ {
proxy_pass http://user-service:8081/; # 注意末尾斜杠
}
location /api/order/ {
proxy_pass http://order-service:8082/;
}
location / {
proxy_pass http://frontend:80/;
}
}
斜杠陷阱:
proxy_pass http://backend/(带斜杠):把 location 前缀替换为/;proxy_pass http://backend(不带斜杠):原样传递完整 URI。
3.3 WebSocket 代理
nginx
location /ws/ {
proxy_pass http://ws-service:9000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s; # 长连接别超时
}
四、负载均衡
4.1 upstream 配置
nginx
upstream backend {
server 192.168.1.10:8080 weight=3; # 权重 3
server 192.168.1.11:8080 weight=1; # 权重 1
server 192.168.1.12:8080 down; # 标记下线(维护)
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
4.2 负载均衡策略
| 策略 | 配置 | 特点 |
|---|---|---|
| 轮询 | 默认 | 平均分发,无权重 |
| 权重 | weight=3 |
按比例分发(性能不均时用) |
| IP 哈希 | ip_hash; |
同一 IP 固定到同一后端(Session 亲和) |
| 最少连接 | least_conn; |
分给连接数最少的后端 |
| 一致性哈希 | hash $request_uri; |
按 key 分配(缓存友好) |
Session 问题:无状态服务(JWT)无所谓;有状态 Session 用 ip_hash 或把 Session 挪到 Redis。
4.3 健康检查
nginx
upstream backend {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
# 主动健康检查(开源版需要第三方模块,商业版/OpenResty 内置)
check interval=5000 rise=2 fall=3 timeout=2000;
}
被动检查:默认配置下,后端挂了 Nginx 会自动摘除(连接失败后),恢复后自动加回。
4.4 实战:Spring Boot 集群
架构:
用户 → Nginx(80) → app1:8080 / app2:8080
↓ 共享
MySQL + Redis
nginx
upstream app_cluster {
least_conn;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080 backup; # 备用节点
}
五、动静分离
5.1 为什么动静分离
静态资源(JS/CSS/图片)让 Nginx 直接返回(几微秒),别让 Java 应用处理(还要起线程)。
nginx
server {
listen 80;
server_name www.example.com;
# 静态资源:Nginx 直接返回
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
root /data/frontend/dist;
expires 7d; # 浏览器缓存 7 天
add_header Cache-Control "public, max-age=604800";
}
# 前端页面
location / {
root /data/frontend/dist;
index index.html;
try_files $uri $uri/ /index.html; # 前端路由 history 模式必配
}
# 后端接口
location /api/ {
proxy_pass http://backend;
}
}
5.2 前端 history 路由 404 问题
Vue/React 用 history 模式路由,刷新 /user/123 时 Nginx 找不到文件------用 try_files 兜底到 index.html。
nginx
location / {
try_files $uri $uri/ /index.html;
}
六、HTTPS 配置
6.1 申请证书
bash
# certbot 免费证书
apt install certbot python3-certbot-nginx
certbot --nginx -d example.com -d www.example.com
或云厂商(阿里云/腾讯云)免费证书。
6.2 配置 HTTPS
nginx
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/cert/example.com.pem;
ssl_certificate_key /etc/nginx/cert/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_session_cache shared:SSL:10m;
location / {
proxy_pass http://backend;
}
}
# HTTP 跳转 HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
6.3 混合 HTTP/HTTPS
坑:HTTPS 页面里请求 HTTP 接口,浏览器拦截(Mixed Content)。要么全站 HTTPS,要么后端接口也走 HTTPS。
七、限流与安全
7.1 限流
nginx
# 定义限流区:rate 10r/s = 每秒 10 个请求
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
server {
location /api/ {
limit_req zone=api_limit burst=20 nodelay; # 突发 20 个
proxy_pass http://backend;
}
}
参数:
rate=10r/s:平均速率;burst=20:突发缓冲 20 个(排队);nodelay:突发请求立即处理(不排队)。
7.2 连接数限制
nginx
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
location /download/ {
limit_conn conn_limit 10; # 同一 IP 最多 10 并发连接
}
7.3 安全头
nginx
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
7.4 隐藏版本号
nginx
server_tokens off;
八、缓存
8.1 静态资源缓存(浏览器端)
nginx
location ~* \.(js|css|png)$ {
expires 30d;
}
8.2 代理缓存(后端响应缓存)
nginx
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=cache_zone:100m max_size=10g inactive=60m;
location /api/ {
proxy_cache cache_zone;
proxy_cache_valid 200 10m; # 200 响应缓存 10 分钟
proxy_cache_key "$scheme$host$request_uri";
add_header X-Cache-Status $upstream_cache_status; # 看命中情况
}
注意:动态接口别乱缓存(数据会过期);缓存要设计 key 和失效策略。
九、日志与监控
9.1 访问日志
nginx
log_format main '$remote_addr - [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'upstream:$upstream_addr $upstream_response_time';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
9.2 按天切割日志
bash
# logrotate 配置 /etc/logrotate.d/nginx
/data/logs/nginx/*.log {
daily
rotate 30
compress
missingok
notifempty
postrotate
/usr/sbin/nginx -s reopen
endscript
}
坑:不切割日志,访问量大的站点一天写几个 G。
9.3 关键指标
$upstream_response_time:后端响应时间(Nginx 日志里看);$upstream_status:后端状态码;- 499:客户端断开(后端处理太久);
- 502/504:后端挂了/超时。
十、常见坑速查
| 现象 | 原因 | 解决 |
|---|---|---|
| 502 Bad Gateway | 后端没起/端口错 | 检查后端、telnet 端口 |
| 504 Gateway Timeout | 后端处理超时 | proxy_read_timeout 调大 |
| 404(前端刷新) | history 路由没配 | try_files /index.html |
| 403 Forbidden | 目录权限/无 index | 检查 root 权限 |
| 499 大量 | 客户端等不及断开 | 后端提速 |
| 静态资源缓存不了 | 没配 expires | 加 expires 头 |
| reload 后不生效 | 配置没写对 | nginx -t 先测 |
| 后端拿不到真实 IP | 没配 X-Real-IP | 加 proxy_set_header |
十一、Nginx 调优要点
nginx
worker_processes auto; # = CPU 核数
worker_connections 10240; # 连接数
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
gzip on; # 压缩
gzip_types text/plain text/css application/json application/javascript;
gzip_min_length 1k;
client_max_body_size 50m; # 上传大小(默认 1M 会报 413)
}
413 坑 :上传文件报 413 Request Entity Too Large------client_max_body_size 默认 1M,要调大。
本章小结
Nginx 的核心心智:server 管入口、location 管分发、upstream 管后端、proxy_pass 管转发。生产上最常用的组合是:反向代理 + 负载均衡 + 动静分离 + HTTPS + 限流。
下一篇讲 Java 并发编程------大厂面试的"必考三件套"之一。
(全文完)