8.1 核心概念
- proxy_cache
- Nginx 把后端响应缓存到本地磁盘,后续相同请求直接由 Nginx 返回,不再打后端。适合缓存可复用的动态响应。
- 缓存键(Cache Key)
- 决定"什么样的请求算同一个缓存"的字符串,默认由 scheme + 方法 + host + URI 组成。设计不当会导致命中率低或错误复用。
- 缓存区(keys_zone)
- 一块共享内存,存缓存条目的键和元数据;实际内容存磁盘。
keys_zone=name:size定义名称和内存大小。 - FastCGI 缓存
- 针对 PHP-FPM 等 FastCGI 后端的缓存(
fastcgi_cache),原理同 proxy_cache,常用于 WordPress 提速。 - 缓存状态 $upstream_cache_status
- 变量,值为 HIT/MISS/EXPIRED/BYPASS 等,写进响应头或日志用于观察命中率。
- worker 调优
- 调整 worker_processes、worker_connections、文件描述符上限、sendfile 等参数,让 Nginx 充分利用硬件。
8.2 配置代理缓存
http {
# 定义缓存路径 + 内存区(放 http 层)
proxy_cache_path /var/cache/nginx
levels=1:2
keys_zone=my_cache:10m
max_size=1g
inactive=60m
use_temp_path=off;
server {
location / {
proxy_pass http://backend;
proxy_cache my_cache;
proxy_cache_valid 200 302 10m; # 200/302 缓存 10 分钟
proxy_cache_valid 404 1m; # 404 缓存 1 分钟
# 把命中状态暴露到响应头,方便调试
add_header X-Cache-Status $upstream_cache_status;
}
}
}
8.3 缓存键与绕过
location / {
proxy_pass http://backend;
proxy_cache my_cache;
# 自定义缓存键(默认已含 host+uri)
proxy_cache_key "$scheme$request_method$host$request_uri";
# 登录用户/带 Cookie 时跳过缓存,直接回源
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
# 后端抖动时用过期缓存兜底(可用性优先)
proxy_cache_use_stale error timeout updating http_500 http_502 http_503;
proxy_cache_lock on; # 相同 key 只放一个请求回源,防击穿
}
别缓存了带用户态的响应
缓存最大的坑是把"张三的个人页"缓存后返回给了李四。凡是随用户/Cookie/Authorization 变化的响应,都要用 proxy_no_cache / proxy_cache_bypass 排除,或把用户标识纳入缓存键。只缓存真正公共的内容。
8.4 FastCGI 缓存(PHP)
http {
fastcgi_cache_path /var/cache/fcgi levels=1:2
keys_zone=php_cache:10m inactive=60m;
server {
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_cache php_cache;
fastcgi_cache_valid 200 10m;
add_header X-FCGI-Cache $upstream_cache_status;
}
}
}
8.5 worker 与连接调优
# main context
worker_processes auto; # = CPU 核心数
worker_rlimit_nofile 100000; # 每 worker 可打开的 fd 上限
events {
worker_connections 16384; # 每 worker 并发连接
multi_accept on; # 一次事件尽量多接连接
use epoll; # Linux 事件模型(通常自动选)
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 1000; # 单连接可复用的请求数
reset_timedout_connection on;
}
先测量再调参
盲目把参数调到天上不会更快,反而可能耗尽内存。用 ab、wrk、k6 压测,观察 CPU、内存、ss -s 连接数和错误日志,找到真正的瓶颈(往往是后端应用或数据库,而非 Nginx 本身)再针对性调整。
8.6 观察缓存命中率
# 在日志格式里加入缓存状态
log_format cachelog '$remote_addr $status $upstream_cache_status '
'"$request" rt=$request_time';
# 统计各命中状态出现次数
$ awk '{print $3}' /var/log/nginx/access.log | sort | uniq -c
8421 HIT
932 MISS
115 EXPIRED
缓存分层
完整的性能栈通常是多层缓存:浏览器缓存(Cache-Control)→ CDN → Nginx proxy_cache → 应用缓存(Redis)→ 数据库。每往前一层拦住请求,成本越低。Nginx 缓存是"离用户很近又几乎零成本"的一层,性价比极高。
8.7 小结与下一步
- proxy_cache 把后端响应存本地磁盘,keys_zone 存键、磁盘存内容。
- proxy_cache_valid 按状态码设时长;no_cache/bypass 排除用户态响应。
- cache_lock + use_stale 防缓存击穿、提升可用性。
- FastCGI 缓存给 PHP 站点大幅提速。
- worker_processes=auto、连接数、sendfile、keepalive 是核心调优点,务必先压测。
- 下一章筑起防线——安全与访问控制。