一句话速览:Nginx 配置的心智模型只有三层——http 块管全局、server 块管一个站点、location 块管一个 URL 路径。三者嵌套,从外到内逐层缩小范围。90% 的 Nginx 配置问题都能用三句话定位:哪个 server 块匹配了请求?哪个 location 匹配了路径?匹配到的指令做了什么?
目录
技术点 1:配置文件的层级结构——http → server → location
Nginx 配置文件(通常在 /etc/nginx/nginx.conf)是嵌套的块结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| worker_processes auto;
events { worker_connections 1024; }
http { sendfile on; keepalive_timeout 65; include /etc/nginx/conf.d/*.conf;
server { listen 80; server_name example.com;
location / { root /var/www/html; index index.html; } } }
|
记忆方式:俄罗斯套娃。http 是最外层(全局 HTTP 设置),server 是中间层(一个站点),location 是最内层(一条 URL 路径的规则)。配置项可以在外层定义、内层继承,内层也可以覆盖外层。
1Panel / 宝塔等面板的做法:通常主配置文件 nginx.conf 里 include /etc/nginx/conf.d/*.conf,每个站点一个 .conf 文件(如 example.com.conf),里面就是一个 server 块。这样加站点只需加文件、不用改主配置。
技术点 2:server 块——虚拟主机,一个 Nginx 托管多个站点
一个 Nginx 可以托管多个站点,靠的是 server_name 区分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| server { listen 80; server_name blog.example.com; root /var/www/blog; }
server { listen 80; server_name api.example.com; proxy_pass http://localhost:3000; }
server { listen 80 default_server; server_name _; return 444; }
|
关键概念:
listen:监听端口,80 是 HTTP、443 是 HTTPS
server_name:匹配请求的 Host 头。Nginx 收到请求后,按 server_name 找对应的 server 块
default_server:没有匹配时的兜底,一个端口只能有一个 default_server
- 多个域名指向同一个站点:
server_name a.com b.com c.com;
技术点 3:location 匹配规则——Nginx 最容易踩坑的地方
location 决定了”这个 URL 路径由什么规则处理”,匹配规则有优先级:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| location = /exact { }
location ^~ /priority { }
location ~ \.php</span> {</span><br><span class="line"> <span class="comment"># 正则匹配(区分大小写),匹配 .php 结尾的路径</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="section">location</span> <span class="regexp">~* \.(jpg|png|css|js) { }
location /api { }
|
优先级从高到低:
= 精确匹配(最高)
^~ 前缀匹配(匹配后不再检查正则)
~ / ~* 正则匹配(按出现顺序,先匹配到的生效)
- 普通前缀匹配(最低,最长前缀优先)
实际例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| server { listen 80;
location ~* \.(css|js|png|jpg|gif|ico)</span> {</span><br><span class="line"> <span class="attribute">root</span> /var/www/static;</span><br><span class="line"> <span class="attribute">expires</span> <span class="number">30d</span>; <span class="comment"># 浏览器缓存 30 天</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment"># /api 反代到后端</span></span><br><span class="line"> <span class="section">location</span> /api {</span><br><span class="line"> <span class="attribute">proxy_pass</span> http://localhost:3000;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 其他路径找静态文件</span></span><br><span class="line"> <span class="section">location</span> / {</span><br><span class="line"> <span class="attribute">root</span> /var/www/html;</span><br><span class="line"> <span class="attribute">try_files</span> <span class="variable">uri $uri/ /index.html; } }
|
SPA 单页应用的 try_files:try_files $uri uri//index.html‘的意思是——先找文件‘uri,再找目录 $uri/,都找不到就返回 index.html(让前端路由处理)。Vue/React 项目部署必配。
技术点 4:反向代理——Nginx 最常见的用途
反向代理就是:用户请求 Nginx → Nginx 转发给后端服务 → 后端返回 → Nginx 转给用户。
1 2 3 4 5 6 7
| location /api { proxy_pass http://localhost:3000; proxy_set_header Host host</span>; <span class="comment"># 把原始 Host 传给后端</span></span><br><span class="line"> <span class="attribute">proxy_set_header</span> X-Real-IP <span class="variable">remote_addr; proxy_set_header X-Forwarded-For proxy_add_x_forwarded_for</span>;</span><br><span class="line"> <span class="attribute">proxy_set_header</span> X-Forwarded-Proto <span class="variable">scheme; }
|
为什么要传这些 header:后端服务收到的请求是 Nginx 发的,不传的话后端以为请求来自 127.0.0.1,拿不到真实用户 IP 和协议。
带路径前缀的代理:
1 2 3 4 5 6 7 8 9
| location /app/ { proxy_pass http://localhost:3000/; }
location /app/ { proxy_pass http://localhost:3000; }
|
末尾 / 的区别是最大的坑:
proxy_pass http://backend/;(带 /)→ /app/foo 变成 /foo
proxy_pass http://backend;(不带 /)→ /app/foo 保持 /app/foo
WebSocket 代理(如果后端用了 WS):
1 2 3 4 5 6 7
| location /ws { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 86400s; }
|
技术点 5:静态文件托管与 try_files
最简单的用途——把 HTML/CSS/JS 文件托管出去:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| server { listen 80; server_name example.com; root /var/www/html;
location / { try_files uri</span><spanclass="variable">uri/ /index.html; }
location /study-plan { try_files uri</span><spanclass="variable">uri.html $uri/ /index.html; } }
|
root vs alias:
root /var/www:location 路径拼在 root 后面。location /img + root /var/www → 找 /var/www/img/xxx
alias /var/www/images:location 路径被替换。location /img + alias /var/www/images → 找 /var/www/images/xxx
记忆方式:root 是”路径拼接”,alias 是”路径替换”。alias 更直观但要注意末尾 / 要对齐。
技术点 6:负载均衡与 upstream
后端有多个实例时,Nginx 可以分发请求:
1 2 3 4 5 6 7 8 9 10 11 12 13
| upstream backend { server 127.0.0.1:3000 weight=3; server 127.0.0.1:3001 weight=1; server 127.0.0.1:3002 backup; }
server { listen 80; location /api { proxy_pass http://backend; } }
|
负载均衡策略:
- 默认:轮询(round-robin),均匀分配
weight=N:按权重分配
ip_hash:同一 IP 固定走同一后端(解决 session 问题)
least_conn:分配给当前连接数最少的后端
1 2 3 4 5
| upstream backend { ip_hash; server 127.0.0.1:3000; server 127.0.0.1:3001; }
|
技术点 7:HTTPS 配置与证书
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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 HIGH:!aNULL:!MD5;
location / { root /var/www/html; } }
server { listen 80; server_name example.com; return 301 https://host</span><spanclass="variable">request_uri; }
|
证书来源:
- Let’s Encrypt(免费,用 certbot 自动申请和续期)
- 阿里云/腾讯云免费 DV 证书
- 付费证书(OV/EV)
HTTP 跳 HTTPS 的坑:后端服务如果需要知道用户用的是 HTTPS,必须传 X-Forwarded-Proto $scheme,否则后端以为请求是 HTTP 的,生成 HTTP 的重定向链接造成无限重定向。
技术点 8:常用运维命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| nginx -t
nginx -s reload
nginx nginx -s stop nginx -s quit
docker exec <容器名> nginx -t docker exec <容器名> nginx -s reload
tail -f /var/log/nginx/access.log tail -f /var/log/nginx/error.log
|
配置变更流程:改配置 → nginx -t 测试 → nginx -s reload 重载。永远先测试再重载,配置语法错误会导致 reload 失败但旧配置仍在跑(不中断服务)。
术语表
| 术语 |
含义 |
| http 块 |
Nginx 配置最外层,管全局 HTTP 设置 |
| server 块 |
虚拟主机,一个 server 对应一个站点 |
| location 块 |
URL 路径匹配规则,一个 location 对应一组 URL |
| root |
文件根目录,location 路径拼在后面 |
| alias |
路径别名,location 路径被替换 |
| try_files |
按顺序尝试文件/目录,找不到用最后一个兜底 |
| proxy_pass |
反向代理,把请求转发给后端 |
| upstream |
后端服务器组,配合 proxy_pass 做负载均衡 |
$uri |
当前请求的 URI(不含参数) |
$host |
请求的 Host 头 |
$remote_addr |
客户端 IP |
default_server |
没有匹配时的兜底 server |
499 |
客户端主动断开(常见于前端超时取消请求) |
502 |
后端服务没起来或端口不对 |
504 |
后端响应超时(Gateway Timeout) |