46 分钟
部署与基础设施工程

Nginx 配置实操:server、location、proxy_pass 与多站点共存

从 Nginx 配置文件的层级结构讲起,手把手写静态托管、反向代理到 Node、转发真实 IP、gzip 缓存与多站点分流,并给出可直接对照的最小配置模板和排错方法

  • 看懂 Nginx 配置的全局/events/http/server/location 嵌套层级
  • 会写静态站点托管与 try_files,会用 proxy_pass 把请求反代到 Node
  • 理解并正确转发 X-Real-IP / X-Forwarded-For / Host 等头部
  • 会用 server_name 与 location 在一台机器上实现多站点共存,会 nginx -t 排错

Nginx 配置是一层层「块」嵌套的

Nginx 配置由指令和花括号块组成,层级从外到内是:全局(main)→ events(连接模型)→ http(全局 HTTP 设置)→ server(一个站点)→ location(站点内按 URL 细分)。主配置 nginx.conf 通常用 include 把每个站点单独放在 sites-available,再软链到 sites-enabled,避免所有站点挤在一个文件。

示例
# 层级关系(示意)
main 全局
└─ events { }            # 连接处理模型(worker_connections 等)
└─ http {                # 所有 HTTP 公共设置(gzip、mime、日志格式)
   └─ server {           # 一个虚拟主机/站点(按 listen + server_name 匹配)
      └─ location / { }  # 按 URL 路径决定怎么处理
      └─ location /api/ { proxy_pass ... }
   }

托管一个静态站点

朋友好学的课程页是静态导出文件,server 块用 root 指定文件目录、index 指定默认首页,try_files 处理前端路由(找不到文件时回退到指定页,这是单页/多页前端路由刷新不 404 的关键):

C / C++
server {
    listen 80;
    server_name pygood.com www.pygood.com;
    root /opt/pyxis/h5/out-h5;      # 静态文件目录
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;  # 先找真实文件,再回退
    }
    location /_next/static/ {               # 带哈希的构建产物可长缓存
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}

反向代理到 Node:proxy_pass 与转发头

动态请求用 location 配合 proxy_pass 转给本机后端。关键是同时转发几个头部,否则后端拿到的是 Nginx 的地址而不是真实用户信息:Host 保留原始域名,X-Real-IP / X-Forwarded-For 透传真实客户端 IP(记日志、限流、风控都要用),X-Forwarded-Proto 告诉后端用户原始是 http 还是 https。

示例
# 同一个 server 里,把 /api 转给 Node 后端
location /api/ {
    proxy_pass http://127.0.0.1:5180;   # 末尾斜杠与否会影响路径拼接
    proxy_http_version 1.1;
    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_read_timeout 120s;            # 大模型/SSE 流式要放大超时
    proxy_buffering off;                # SSE 流式需要关闭缓冲,边生成边推
}
⚠️两个为流式接口必改的点

大模型逐字、TTS 流式走 SSE 时,Nginx 默认会缓冲后端响应、想攒一批再发,导致「半天不出字、最后一起蹦」。必须 proxy_buffering off(或对该 location 设 X-Accel-Buffering no),并把 proxy_read_timeout 调大,否则长连接会被 Nginx 按默认 60 秒判超时返回 504。这是把 SSE 部署上线后最常见的坑。

location 匹配规则与多站点共存

Nginx 用 server_name 区分不同域名的站点(虚拟主机);当请求到达,先按 listen 端口、再按 server_name 匹配 server,server 内再按 location 规则匹配路径。location 有前缀匹配和 =(精确)、^~、~(正则)等优先级。朋友好学正是利用「精确 location 优先」让同一台 80 端口上两个产品共存:默认落到另一个产品,而朋友好学的具名 API 路径被精确分流到自己的 Node。

示例
# 多后端负载均衡:用 upstream 命名一组后端
upstream pyxis_node {
    server 127.0.0.1:5180;
    # server 127.0.0.1:5181;   # 扩容时加机器即可
    keepalive 32;
}
# 之后 proxy_pass http://pyxis_node;

# 多站点:另一个 server 用不同 server_name
server {
    listen 80 default_server;   # 没匹配到域名时的兜底站点
    server_name _;
    location / { proxy_pass http://127.0.0.1:8799; }
}
💡gzip 与安全头,一处配置全站受益

在 http 块统一开 gzip 压缩文本类响应(JS/CSS/JSON 体积可降 70% 左右),并统一加安全响应头(如 X-Content-Type-Options: nosniff、X-Frame-Options 防点击劫持)。这些写一次,所有 server 共享,正是「统一咽喉」的红利。

改完怎么生效、出错怎么查

Shell
sudo nginx -t              # ① 永远先校验语法,会提示哪一行错
sudo systemctl reload nginx # ② 语法 OK 再热加载(不断连接,优于 restart)
# 排查:
sudo tail -f /var/log/nginx/access.log   # 访问日志:请求有没有到 Nginx
sudo tail -f /var/log/nginx/error.log    # 错误日志:502/配置错看这里
curl -I http://127.0.0.1                 # 本机先验证响应头
🚫502 先看后端在不在、路径对不对

Nginx 返回 502 Bad Gateway,含义是「我按 proxy_pass 去找后端,但对方没正常应答」。排查顺序:后端进程是否真的在跑、端口对不对(ss -ltnp);proxy_pass 地址/端口、末尾斜杠导致的路径是否正确;后端是否崩在启动。问题永远在 Nginx 之后,而不是 Nginx 自己。

选择题

大模型流式对话上线后,用户反馈「要等很久文字才一次性全蹦出来」,在 Nginx 层最可能要调整的是?

本节小结

Nginx 配置层级 main→events→http→server→location,站点用 include 分文件管理。静态托管用 root/index/try_files(前端路由回退避免刷新404)、带哈希资源设长缓存。反代用 proxy_pass 指向 127.0.0.1 后端,并转发 Host、X-Real-IP、X-Forwarded-For、X-Forwarded-Proto;SSE 流式必须 proxy_buffering off + 放大 read_timeout。多站点靠 server_name 虚拟主机、location 前缀/精确/正则优先级分流,多后端用 upstream(可 keepalive、可扩容、可负载算法),gzip 与安全头在 http 统一配。改动先 nginx -t 再 reload,access/error 日志定位,502 先查后端进程、端口与 proxy_pass 路径。

资深工程师加餐

底层原理 · 大厂视角 · 工程经验,点卡片展开

把会话、上传文件、定时任务状态从应用进程里挪到 Redis、对象存储或数据库后,任何一台应用实例都能处理任何请求,扩容就是多开几个实例挂到负载均衡后面。反过来,只要状态留在某台机器的内存里,它就既无法横向扩容,也无法滚动更新(一重启用户就掉线)。面试答「如何支撑更高并发」,先讲无状态化,再谈加机器和缓存。