写 Nginx 配置时,最容易出问题的地方往往不是“会不会启动”,而是路径被转发成了另一个样子:多了一级目录、少了前缀、出现双斜杠,或者静态文件明明存在却 404。
要把这类问题排清楚,先抓住三个点:location 怎么匹配,proxy_pass 尾斜杠怎么改写路径,root 和 alias 到底差在哪。
先看 Nginx 配置结构
Nginx 配置按上下文组织,常见层级可以这样记:
main:全局配置,比如 worker、pid、日志。events:连接处理模型和连接数。http:HTTP 服务、日志、压缩、缓存和代理。server:一个虚拟主机。location:某一类 URI 的处理规则。stream:TCP / UDP 代理。
一个最小反向代理配置大概长这样:
worker_processes auto;
events {
worker_connections 2048;
}
http {
include mime.types;
default_type application/octet-stream;
upstream app_backend {
server 127.0.0.1:8080 weight=10;
server 127.0.0.1:8081 weight=10;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://app_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;
}
}
}
真正上线时还要补日志、超时、缓存、安全和 HTTPS,但理解反向代理主线,先从这几块就够了。
location 匹配先看优先级
location 不是按配置文件里谁写在前面就一定谁生效。常见匹配方式有几类:
location = /abc {}:精确匹配,只匹配/abc。location /abc {}:普通前缀匹配,可匹配/abc、/abc/、/abcd。location ^~ /static/ {}:前缀命中后停止继续匹配正则。location ~ \.jpg$ {}:正则匹配,区分大小写。location ~* \.jpg$ {}:正则匹配,不区分大小写。
优先级可以粗略记成:
- 先看精确匹配
=。 - 再看最长前缀匹配,如果命中
^~就停止。 - 再看正则匹配
~和~*。 - 最后使用普通前缀匹配结果。
排障时不要只盯某一个 location,要确认请求实际命中了哪条规则。
proxy_pass 的尾斜杠最容易踩坑
proxy_pass 是否带 URI、是否以 / 结尾,会影响转发到后端的路径。
假设用户访问:
/test/xxoo.html
常见结果可以这样记:
location /test/ { proxy_pass http://upstream/; }:转到后端时路径通常变成/xxoo.html。location /test/ { proxy_pass http://upstream; }:转到后端时路径通常保留/test/xxoo.html。location /test/ { proxy_pass http://upstream/api/; }:转到后端时路径通常变成/api/xxoo.html。location /test/ { proxy_pass http://upstream/api; }:很容易得到/apixxoo.html这种不是你想要的拼接结果。
所以,代理 API 时最好固定一种写法,不要混用。
比如你希望外部访问 /api/user,后端实际收到 /user,可以用:
location /api/ {
proxy_pass http://backend/;
}
如果你希望后端也收到 /api/user,可以用:
location /api/ {
proxy_pass http://backend;
}
这两种都可以,关键是团队要知道自己选的是哪一种。
root 和 alias 不是一回事
静态文件 404 时,root 和 alias 也是高频坑。
root 会把 location 匹配到的 URI 继续拼到根目录后面。
location /test/ {
root /www/abc;
}
访问 /test/a.jpg 时,Nginx 会去找:
/www/abc/test/a.jpg
alias 则是用指定目录替换掉 location 前缀。
location /test/ {
alias /www/abc/;
}
访问 /test/a.jpg 时,Nginx 会去找:
/www/abc/a.jpg
如果你本来想把 /static/ 映射到某个真实目录,通常要认真判断应该用 root 还是 alias。这里写错时,配置语法可能没问题,但线上就是找不到文件。
常用命令先记这几个
改配置前后,先养成检查和 reload 的习惯:
nginx -t # 检查配置
nginx -s reload # 重新加载配置
nginx -s quit # 正常关闭
nginx -s stop # 快速关闭
nginx -s reopen # 重新打开日志文件
Homebrew 安装时常见路径:
配置文件:/usr/local/etc/nginx/nginx.conf
默认根目录:/usr/local/var/www
Apple Silicon 根目录:/opt/homebrew/var/www
不同安装方式路径可能不同,排障时可以先用 nginx -t 看它实际读取了哪份配置。
Gzip 和性能参数别一上来拉满
常见 Gzip 配置可以这样写:
gzip on;
gzip_disable "msie6";
gzip_proxied any;
gzip_min_length 1k;
gzip_comp_level 4;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
注意三点:
- 小文件压缩收益低,
gzip_min_length不要太小。 - 图片、视频这类已压缩内容通常不需要再 gzip。
- 压缩等级越高不一定越好,要看 CPU 和响应体大小。
常见性能参数也先从稳妥配置开始:
worker_processes auto;
worker_rlimit_nofile 10000;
events {
worker_connections 2048;
multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
client_header_timeout 10;
client_body_timeout 10;
reset_timedout_connection on;
send_timeout 30;
}
这些参数不是越大越好。比如 worker_connections 还要结合系统文件句柄上限、后端连接数、机器资源和业务峰值来看。
限流配置要先观察正常峰值
接口限流可以用 limit_req 和 limit_conn:
limit_req_zone $binary_remote_addr zone=per_ip_req:10m rate=20r/s;
limit_conn_zone $binary_remote_addr zone=per_ip_conn:10m;
server {
location /api/ {
limit_req zone=per_ip_req burst=5 nodelay;
limit_conn per_ip_conn 20;
proxy_pass http://app_backend;
}
}
这里要注意:
- 先看正常峰值,再定 rate 和连接数。
burst允许短时突发。nodelay表示突发请求不排队等待,直接按规则处理。- 限流太紧会误伤正常用户,太松又挡不住异常流量。
排障顺序
如果 Nginx 反向代理不符合预期,可以按这个顺序查:
- 先跑
nginx -t,确认配置语法和实际配置文件路径。 - 看请求命中了哪个
server_name和location。 - 检查
proxy_pass是否带尾斜杠,以及后端实际收到的路径。 - 静态文件 404 时,确认用了
root还是alias。 - 看
error.log,再用access.log分析状态码和上游耗时。 - 必要时临时加更细的日志字段,确认 upstream、URI 和转发头。
小结
Nginx 反向代理配置不难,但路径规则很容易让人误判。
可以先记住几句话:
location要按匹配优先级看,不是只看文件顺序。proxy_pass带不带尾斜杠,会影响转发到后端的 URI。root是把 URI 拼到根目录后面,alias是替换 URI 前缀。- Gzip、连接数和限流参数要结合实际流量,不要一上来写满。
- 改配置先
nginx -t,再 reload,最后看日志确认请求真实走向。
把这几个点搞清楚,绝大多数 Nginx 反向代理和静态资源路径问题都会好排很多。




