Nginx 反向代理配置实战:从入门到生产环境优化
反向代理是 Nginx 最核心的功能之一,几乎每个站长在服务器运维过程中都会用到。无论是负载均衡、SSL 终端代理,还是为后端服务统一入口,Nginx 反向代理都是必不可少的工具。本文将从一个草根站长的实际需求出发,系统讲解 Nginx 反向代理的配置方法和生产环境优化技巧。
什么是反向代理
简单来说,反向代理就是代理服务器接收客户端请求,然后将请求转发到后端服务器(如 Apache、Tomcat、Node.js 等),再将后端响应返回给客户端。对客户端来说,它们只知道代理服务器的地址,不知道后端服务器的存在。
反向代理的核心价值在于:
- 安全隔离:隐藏后端服务器的真实 IP,防止直接攻击
- 负载均衡:将请求分发到多台后端服务器,提升处理能力
- 统一入口:多个服务共享一个域名,通过路径或子域名区分
- SSL 卸载:由 Nginx 处理 HTTPS,后端服务只处理 HTTP
- 缓存加速:缓存静态资源和 API 响应,减轻后端压力
基础反向代理配置
先来看一个最简单的 Nginx 反向代理配置。假设我们有一个在本机 8080 端口运行的 Node.js 应用,希望通过 80 端口以标准域名方式对外提供服务:
server {
listen 80;
server_name 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_set_header X-Forwarded-Proto $scheme;
}
}这段配置的核心指令是 proxy_pass,它指定了请求转发到的后端地址。后面的四个 proxy_set_header 指令用于将客户端的原始信息传递给后端,这是非常重要的,因为后端应用通常需要知道客户端真实的 IP 地址和请求协议,否则获取到的 IP 全是 Nginx 服务器的内网地址。
常用代理头部详解
在生产环境中,以下几个请求头需要特别关注:
- Host:客户端原始请求的 Host 头部,后端应用依赖它来生成正确的重定向 URL
- X-Real-IP:客户端的真实 IP 地址
- X-Forwarded-For:记录经过的代理链,每一级代理追加一个 IP
- X-Forwarded-Proto:客户端请求的协议(http 或 https),用于后端生成正确的协议链接
如果后端应用使用了 WebSocket(例如常见的实时面板、在线聊天功能),还需要额外添加以下配置:
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";多站点反向代理配置
个人站长经常遇到这样的情况:一台服务器上运行了多个服务,比如一个博客、一个图床、一个导航站,如何通过同一个 IP 的 80/443 端口对外提供服务?答案是使用不同域名或子域名区分。
server {
listen 80;
server_name blog.example.com;
location / {
proxy_pass http://127.0.0.1:8001;
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;
}
}
server {
listen 80;
server_name img.example.com;
location / {
proxy_pass http://127.0.0.1:8002;
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;
}
}每个 server 块绑定一个域名,Nginx 会根据请求的 Host 头部自动路由到对应的后端服务。
负载均衡配置
当网站的流量增长到单台服务器难以承载时,可以通过 Nginx 的 upstream 模块实现负载均衡:
upstream backend {
# 负载均衡算法:默认轮询
server 192.168.1.10:8080 weight=3;
server 192.168.1.11:8080 weight=2;
server 192.168.1.12:8080 backup;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
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;
}
}Nginx 支持多种负载均衡算法:
- 轮询(默认):按顺序轮流分配请求
- weight(权重):按权重比例分配,权重越高分配的请求越多
- ip_hash:根据客户端 IP 哈希分配,保证同一 IP 始终访问同一台后端
- least_conn:分配给当前连接数最少的后端
backup 标记的服务器只有在其他服务器都不可用时才会被使用,适合作为灾备节点。
缓存配置优化
反向代理缓存可以显著提升网站响应速度,减少后端服务器的负载:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=mycache:10m max_size=1g inactive=60m;
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_cache mycache;
proxy_cache_valid 200 302 60m;
proxy_cache_valid 404 1m;
proxy_cache_key "$scheme$request_method$host$request_uri";
add_header X-Cache-Status $upstream_cache_status;
}
}proxy_cache_path 用于定义缓存存储路径和参数。keys_zone 指定共享内存区域名称和大小,10MB 大约可以存储 8 万个缓存键。inactive 表示缓存文件在 60 分钟内未被访问则自动删除。
添加 X-Cache-Status 响应头可以方便地调试缓存命中情况,返回 HIT 表示命中缓存,MISS 表示未命中。
SSL 与 HTTPS 配置
为反向代理配置 SSL 证书是让网站支持 HTTPS 的标准做法:
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.pem;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
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;
}
}
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}这种配置模式下,后端服务只需要处理 HTTP 请求即可,SSL 加密解密全部由 Nginx 完成,这就是前面提到的 SSL 卸载。
生产环境优化建议
根据我多年的运维经验,总结以下几点在部署 Nginx 反向代理时特别需要注意的优化事项:
超时时间调整:默认的代理超时时间(60 秒)对于某些耗时较长的接口可能不够。根据业务需求调整:
proxy_connect_timeout 30s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;缓冲区调优:合理设置缓冲区可以减少磁盘 I/O,提升响应速度:
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;连接复用:通过 keepalive 配置减少后端连接的建立开销:
upstream backend {
server 127.0.0.1:8080;
keepalive 32;
}
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://backend;
}错误处理:当后端服务不可用时,可以返回自定义错误页面而不是直接抛出 502:
proxy_intercept_errors on;
error_page 502 503 504 /50x.html;日志优化:记录代理相关的日志信息,方便排查问题:
log_format proxy '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'upstream:$upstream_addr status:$upstream_status '
'cache:$upstream_cache_status';
access_log /var/log/nginx/proxy_access.log proxy;常见的坑与排查方法
在实际配置过程中,有几个常见问题需要特别注意。
第一个坑是代理后获取不到客户端真实 IP。很多后端应用需要通过 request.getRemoteAddr() 或 $_SERVER['REMOTE_ADDR'] 获取客户端 IP,如果 Nginx 没有正确传递 X-Real-IP 头部,获取到的就是 Nginx 服务器的内网地址。解决办法就是确保 proxy_set_header X-Real-IP $remote_addr; 已配置,并且后端应用正确读取了 X-Real-IP 或 X-Forwarded-For 头部。
第二个坑是代理后 HTTPS 重定向变成 HTTP。某些后端应用根据请求协议生成重定向 URL,如果 Nginx 没有传递 X-Forwarded-Proto 头部,后端收到的是 HTTP 请求,生成的重定向 URL 就是 HTTP 而非 HTTPS。解决办法是配置 proxy_set_header X-Forwarded-Proto $scheme;,并在后端应用中配置信任代理。
第三个坑是 WebSocket 连接失败。如果应用使用了 WebSocket(比如一些在线终端或实时面板),需要在 location 块中添加 Upgrade 相关的头部信息。
排查问题时,可以先用 curl 测试 Nginx 代理是否正常工作:
curl -I -H "Host: example.com" http://127.0.0.1
curl -I http://example.com同时检查 Nginx 的错误日志是非常有效的排查手段:
tail -f /var/log/nginx/error.log总结
Nginx 反向代理是个人站长必须掌握的技能之一。从基础的端口转发到复杂的负载均衡,再到 SSL 卸载和缓存加速,合理配置反向代理不仅可以提升网站的安全性和性能,还能让服务器资源的利用更加高效。希望本文的实战经验能帮助到各位站长朋友们。