Nginx反向代理与缓存优化实战:给网站装上加速引擎
作为草根站长,手头可能只有一台低配 VPS,却要跑好几个网站。如果每个站点都直接暴露在公网上,不仅资源消耗大,安全性也是隐患。用 Nginx 做反向代理加缓存层,是我这些年压榨服务器性能最有效的方案。
什么是反向代理
反向代理就是让 Nginx 作为中间人,接收用户的请求,然后转发给后端真实的 Web 服务器(Apache、PHP-FPM、Node.js 等),再把后端返回的结果回传给用户。用户全程只跟 Nginx 打交道,看不到后端的存在。
这样做有三个明显的好处:第一,后端服务被隐藏起来,减少了攻击面;第二,Nginx 处理静态文件和并发连接的能力远超 Apache,能大幅提升吞吐量;第三,可以在代理层统一做 SSL 卸载、缓存、限流、日志等工作。
基础反向代理配置
先看一个最基础的反向代理配置,把 Nginx 放在 Apache 前面:
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 的作用是把用户真实信息透传给后端。如果不传 X-Real-IP,后端看到的 IP 永远是 127.0.0.1,日志和限制都会失效。
开启缓存层
纯代理只能解决隐藏后端的问题,对性能提升有限。真正让网站起飞的是缓存。Nginx 的 proxy_cache 功能可以把后端返回的页面缓存到磁盘上,同样的请求直接返回缓存,不再请求后端。
# 在 http 块中定义缓存路径
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=mycache:10m max_size=1g inactive=60m use_temp_path=off;
server {
listen 80;
server_name example.com;
location / {
proxy_cache mycache;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_valid 200 302 60m;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503;
proxy_cache_background_update on;
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;
}
}解释一下关键参数:
keys_zone=mycache:10m:分配 10MB 共享内存用来缓存索引键,大约可以管理 8 万个键。max_size=1g:缓存文件总大小上限 1GB,超过后 Nginx 会自动清理最少使用的缓存。inactive=60m:缓存文件如果 60 分钟没有被访问,就会自动删除。proxy_cache_valid:对不同 HTTP 状态码设置缓存有效期。200 和 302 缓存 60 分钟,404 只缓存 1 分钟。proxy_cache_use_stale:后端宕机或出错时,允许返回过期的缓存。这对提高可用性非常重要。
按需清除缓存
缓存最头疼的问题就是更新。文章发布后,首页和分类页的缓存还是旧的。解决办法是安装 ngx_cache_purge 模块,然后配置一个清除缓存的接口:
location ~ /purge(/.*) {
allow 127.0.0.1;
allow 你的IP;
deny all;
proxy_cache_purge mycache "$scheme$request_method$host$1";
}然后在发布文章时,用 curl 请求一下要清除的 URL 即可:
curl -s http://127.0.0.1/purge/
curl -s http://127.0.0.1/purge/article/123.htmlSSL 卸载
在代理层统一处理 HTTPS,后端只跑 HTTP,能让配置简化很多:
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header X-Forwarded-Proto https;
# 缓存配置同上
}
}用 Certbot 自动续期证书,配合上面的代理,就能轻松跑满 A+ 评分。
动静分离
把静态资源(图片、CSS、JS)直接交给 Nginx 处理,不走后端:
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2)$ {
expires 30d;
add_header Cache-Control "public, immutable";
# 直接读取文件系统,不经过代理
root /var/www/html;
access_log off;
}这套配置能让后端压力减少 80% 以上。我的博客之前 Apache 平均负载在 2.5 左右,套上 Nginx 缓存加动静分离后,负载降到了 0.3。
常见问题
后端获取不到真实 IP
确认代理配置中传了 X-Real-IP 和 X-Forwarded-For 头,并且后端的日志格式使用了真实 IP 变量。对于 PHP 应用,还需要设置:
fastcgi_param HTTP_X_REAL_IP $remote_addr;缓存没有命中
检查 proxy_cache_key 是否包含了 $request_method,有时候 POST 请求也会被缓存导致奇怪的问题。另外确认缓存目录的权限是否正确。
代理超时
后端响应慢时,Nginx 默认 60 秒超时。对于长耗时的操作,可以适当调大:
proxy_connect_timeout 30s;
proxy_read_timeout 120s;
proxy_send_timeout 60s;总结
Nginx 反向代理加缓存是草根站长性价比最高的性能优化方案。不需要升级服务器配置,只需要花点时间调整 Nginx 配置,就能让网站速度提升一个档次。上面给出的配置已经在我自己的多台 VPS 上稳定运行了两年多,值得收藏尝试。
实际部署时建议先在一台测试站点上验证缓存策略,观察一段时间的命中率和后端负载,再逐步推广到所有站点。缓存虽好,但过期策略不当会让用户看到旧内容,反而影响体验。