拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Nginx反向代理配置实战:从核心原理到负载均衡与故障排查

Nginx反向代理配置实战:从核心原理到负载均衡与故障排查 每次有人让我帮忙排查“Nginx 反向代理配置”的问题我基本不用看代码就能猜到一半的坑要么是proxy_pass的路径没写明白要么是前端拿到 502 后一群人干瞪眼。Nginx 这个名字在服务端几乎无人不晓高性能、高并发、轻量这些词被聊烂了但真正能一次把反向代理配妥的人其实不多。这篇文章我不想按官方文档的顺序啰嗦一遍而是从我这些年踩过的坑、改过的配置、背过的面试题里挑出最实用的一条线讲清楚什么是反向代理Nginx 在什么场景下可以做什么安装时有哪些选择核心配置怎么拆负载均衡怎么做SSL 和 WebSocket 这些进阶玩法怎么接最后再给你一份常见问题排查表。这套内容适合两类人一是刚接触服务器、准备把自己写的项目部署上线的新手二是已经会装 Nginx 但每次配置都靠复制粘贴、出了问题就要搜半天的初级运维。看完之后至少你能独立写出一份能上生产的反向代理配置也能在面试时把“反向代理和正向代理的区别”讲得让面试官点头。1. 反向代理不是玄学先搞清楚它解决什么问题1.1 所谓“反向”到底反在哪里代理这个词大家不陌生正向代理最常见的就是公司内网里那台“上网代理服务器”。你在浏览器里配置代理所有请求先发给代理服务器由它替你访问外网再拿回来。这个模式下真正访问资源的服务器并不知道是你发起的请求它只认识代理服务器的地址。这里面的关键点是正向代理是站在客户端侧的为客户端服务的。反向代理刚好掉了个头。客户端发请求时根本不知道内部有多少台真实服务器它把所有请求统一打给对外暴露的那台机器——也就是 Nginx。Nginx 再按照配置规则把请求转发给一台或多台内部的应用服务器。客户端只认 Nginx对内实际由谁处理客户端完全不感知。所以反向代理是站在服务端侧的为后端服务器服务的。用生活里的例子打比方正向代理就像是帮你代购的熟人你告诉他想要什么他去买回来给你卖家看到的是这位熟人在采购。反向代理则像公司前台访客说“我要找技术部”前台核实后把访客领到对应的工位访客全程不需要知道技术部到底在三楼还是五楼。这个“领路”动作就是反向代理最核心的职责。1.2 有了它开发运维能省下哪些时间反向代理解决的问题不是我第一个想到的而是实际被逼出来的。举一个最常见的场景公司买了多台服务器分别跑着订单服务、支付服务、用户服务端口不一有的 8080有的 8081还有的 9090。你总不能让用户去记这些端口也不可能给每个服务单独买一个域名。这时候在服务器最前面放一台 Nginx监听 80/443 端口然后把不同路径分别转发到对应服务。对外只有一个域名一种访问方式内部的服务怎么编排完全由后端决定调整起来也不影响用户。再比如运维层面经常需要做灰度发布或负载均衡。今天新增一台实例想在老集群里先放少量流量观察一下直接改 Nginx 的 upstream 配置把新实例权重调低秒级生效。服务挂了需要摘除也是改一行配置的事不用动业务代码。从安全角度讲反向代理还能藏住内网的真实结构。外部扫描只能看到 Nginx 这台“入口机”后端应用端口不对公网开放攻击面立刻小了很多。加上我们后文要说的限流、IP 白名单、SSL 终止Nginx 实际上充当了应用防火墙和数据加密边缘的双重角色。1.3 我要去哪里看即可但有人困惑它和 Tomcat 冲突吗这是个在技术社区里反复出现的误会。很多 Java 开发者装了 Tomcat也装了 Nginx然后发现防火墙只开了 80 端口Tomcat 的 8080 从外面访问不了就以为是配置对撞了。其实两者根本不冲突。Tomcat 是应用容器负责跑 Servlet、JSP 或者 Spring Boot 打出的包Nginx 是 Web 服务器和反向代理负责接收 HTTP 请求并决定把请求交到谁手里。生产环境里最常见的组合就是“Nginx80→ Tomcat8080”根本不会端口打架。你把 Tomcat 的端口改成 8080、8081 多个实例再把 Nginx 指向这些地址就搭建起了一套最原始的负载均衡集群。这个结构在任何 Java 项目中都能直接复用和 Spring Cloud 这种微服务体系也不冲突Nginx 在七层做流量入口注册中心在应用内部做服务发现各干各的一点都不矛盾。2. 动手前的第一件事Nginx 安装的几种姿势2.1 从官网下载还是国内镜像差别在哪如果你只是想在本地 Windows 开发环境里快速体验一把直接从官网nginx.org/en/download.html下载 Windows 版本即可。官网同时提供主线版本Mainline、稳定版本Stable和历史版本Legacy。我的建议是生产环境优先选稳定版因为主线版迭代快新功能多但相对的稳定性验证时间短测试环境则可以用主线版提前感受新特性。但国内网络环境大家都懂官网下载偶尔会慢到让人怀疑人生。备选方案是使用国内云厂商提供的开源镜像站像阿里云镜像、华为云镜像都有 Nginx 的软件包同步下载速度和稳定性都有保障。装完之后可以顺手校验一下版本和校验和防止下载到不完整的文件。在 Linux 上我更推荐包管理器安装省心、干净、易卸载。这里有个小经验虽然包管理器装出来的版本可能不是最新但系统集成度极高systemd 服务脚本、默认目录结构、日志轮转全都帮你配好了对大多数人来说这才是“开箱即用”的正解。2.2 Windows 下的 Nginx解压就能跑的轻量方案Windows 版本的 Nginx 不需要安装程序它就是一个压缩包解压即用。我建议你把目录放到一个不含中文和空格的路径比如D:\nginx-1.26.2否则某些模块在解析路径时可能出现奇怪的问题。目录结构里最重要的就是conf/nginx.conf它是唯一的主配置文件。启动方式是在命令行里切换到 Nginx 目录执行start nginx注意这里不要直接双击nginx.exe否则弹出的黑窗口会一直挂着而且关掉窗口后进程经常残留。使用start命令可以让它在后台运行。停止和重载指令分别是nginx -s stop nginx -s reload日常改完配置文件验证语法用nginx -t它只做检查不生效等确认无误后再 reload。想确认进程是否真的起来了用tasklist /fi imagename eq nginx.exe如果看到两个 nginx 进程那是正常的一个 master 一个 worker。Windows 下 Nginx 的性能表现弱于 Linux但拿来做本地开发调试、测试反向代理配置完全没有问题。2.3 Linux 安装AlmaLinux 9 和 Ubuntu 都能一条命令搞定在生产环境我强烈建议用 Linux。以 AlmaLinux 9 这种 RHEL 系发行版为例直接用 dnf 安装sudo dnf install -y nginx sudo systemctl enable --now nginx nginx -vUbuntu 或 Debian 系则是sudo apt update sudo apt install -y nginx sudo systemctl enable --now nginx安装完成后用systemctl status nginx可以看到服务处于 active (running) 状态。默认的站点根目录在/usr/share/nginx/html配置文件在/etc/nginx/nginx.conf子站点配置目录是/etc/nginx/conf.d/。记住这几个路径后面修改配置时不会迷路。AlmaLinux 9 有一点点特殊。RHEL 9 的 AppStream 仓库默认提供的 Nginx 版本往往不是最新的如果你有硬性版本要求比如需要 1.25 之后的特性那么建议到官网下载源码包编译或者使用 EPEL 源看有没有更高版本可装。生产环境未必需要最新版稳定压倒一切但如果你在编译安装平滑升级时正好卡在版本问题上这就是你能排查的方向之一。2.4 编译安装和高阶注意事项源码编译安装 Nginx 是一些大型互联网公司的传统做法。它可以自由控制模块、安装路径和编译参数可以把不需要的模块剔掉以减少体积和攻击面。编译安装的大致流程是sudo dnf install -y gcc pcre-devel zlib-devel openssl-devel wget https://nginx.org/download/nginx-1.26.2.tar.gz tar -zxvf nginx-1.26.2.tar.gz cd nginx-1.26.2 ./configure --prefix/usr/local/nginx \ --with-http_ssl_module \ --with-http_stub_status_module \ --with-http_realip_module make -j$(nproc) sudo make install这里有几个关键依赖包pcre用于支持正则表达式重写zlib用于 gzip 压缩openssl用于 HTTPS。缺了哪个编译阶段就会直接报错。我记得第一次编译时因为没装 pcre-develconfigure 阶段就卡住了查了半天才反应过来是少了头文件。编译安装的路径和包管理器安装差异很大Nginx 主程序在/usr/local/nginx/sbin/nginx配置文件在/usr/local/nginx/conf/nginx.conf。这时候没有 systemd 管理脚本启动、重启得手动执行nginx和nginx -s reload建议自己写一份 systemd service 文件否则服务器一重启 Nginx 是不会自动起来的。顺带提一句和本文主题有点关系但不属于 Nginx 的题外话每次部署前后端项目新手往往会同时安装 MySQL、Git、Node.js、Java 这些环境并且偶尔因为环境变量配置错误而折腾半天。这类环境变量问题和 Nginx 没有直接依赖但如果你的 Java 项目需要读取环境变量来启动后端服务而环境变量没配好那 Nginx 即使把请求转发到 8080 端口也会因为后端根本没起来而返回 502。排查连接问题的时候先确认后端进程在不在别把所有问题都甩给 Nginx。3. 核心配置拆解写一份能直接上生产的反向代理3.1 最小可用的 server 块Nginx 的主配置本质就是一个层级结构每个server {}代表一个虚拟主机每个location {}代表一种路径匹配规则。一个最简单但功能完整的反向代理配置如下server { listen 80; server_name api.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; } }listen指定 Nginx 监听的端口server_name是虚拟主机的识别名。当外部请求携带的 Host 头是api.example.com时Nginx 就会走进这个 server 块处理请求。proxy_pass是灵魂指令它把请求转发给http://127.0.0.1:8080。这里有几个细节值得死磕。第一proxy_set_header Host $host;这行非常关键。如果不设置后端应用收到的 Host 可能是 Nginx 的 IP 或者端口很多框架在生成绝对链接、校验 CSRF、判断域名时就会出错。设置成$host可以让后端感觉请求就是直接发给它自己的。第二X-Real-IP和X-Forwarded-For用于记录真实客户端 IP。后端拿不到用户真实 IP 的时候十有八九是这两行没配。第三像 Spring Boot 这类框架如果想正确识别 HTTPS还需要看X-Forwarded-Proto上面的配置里也带了。3.2 proxy_pass 的斜杠陷阱面试和实战都爱考先看两个配置location /api/ { proxy_pass http://backend:8080/; }和location /api/ { proxy_pass http://backend:8080; }区别在于proxy_pass后面是否带路径。不带路径时Nginx 会将location匹配到的完整 URI 原样转发给后端。也就是说请求/api/user/list后端最终收到的还是/api/user/list。带路径时情况完全不同Nginx 会把location中匹配到的那一段前缀“吃掉”再拼接上剩余路径。还是请求/api/user/list因为匹配前缀是/api/后端最终收到的是/user/list。这个特性用好了可以做接口前缀隐藏用坏了就是“为什么前端明明请求/api/user后端却说 404”的经典事故。我建议大家在写配置时统一一个习惯要么后端明确要求不带前缀要么就全都带上斜杠别今天写一种明天写另一种时间一长自己都记不住。3.3 把多个站点拆到独立文件管理不要把所有 server 块都堆在nginx.conf一个文件里那会让几千行配置挤在一起改一个站点都要小心翼翼。标准做法是利用 include 机制。Linux 安装的 Nginx 默认会在主配置末尾包含include /etc/nginx/conf.d/*.conf;所以你可以在/etc/nginx/conf.d/下为每个业务建一个独立文件比如api.conf、admin.conf、map.conf。每个文件里只写自己的 server 块。这样做的好处是互不污染、便于 git 管理、出问题时能快速定位到具体文件坏处是如果文件命名太随意过段时间你会发现它变成了“无人认领的配置垃圾场”。Windows 版的conf/nginx.conf默认只配置了一个示例 server没有自动 include 子目录。你可以手动在 http 块里加一行指定加载conf/sites/*.conf下的文件然后自行创建这个目录。改完目录结构后记得执行nginx -t检查语法然后 reload 生效。3.4 实际场景内网地图服务是怎么做反向代理的这是我从热搜词里看到的一个挺有意思的问题内网要反向代理地图供内网使用以百度地图为例应该怎么做。这个需求我见过很多次企业内部开发的系统比如物流管理、工地监控需要在地图上展示设备和车辆位置但前端直接访问公网地图服务既慢又不可控还容易遇到跨域限制。做法并不复杂。首先确认企业内部使用的地图服务是否有合法授权无论是百度地图还是其他商业地图服务都要求开发者账号、AK/SK 之类的认证。接下来在 Nginx 上新建一个专门的地图入口例如把/map/路径反向代理到后端地图地址同时在代理过程中统一追加认证参数location /map/ { proxy_pass https://map-backend.internal.example.com/; proxy_set_header Host map-backend.internal.example.com; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 统一追加授权AK避免每个前端都暴露密钥 set $full_uri $request_uri; if ($args !~* ak) { rewrite ^ $request_uri?akYOUR_AK last; } }当然上面的 rewrite 写法只是一个粗略示意生产环境更推荐在应用层维护一个服务端代理接口由后端去拼接密钥。但你已经能看出关键思路了Nginx 可以做内网流量的统一入口把需要外部访问的地址收敛成一个内网域名前端应用只对接这个内网域名网络拓扑简单密钥也不容易泄露。顺带一提把 Nginx 当作共享文件服务器也是一个高频需求也就是热搜里提到的“nginx 共享文件”。只需在 location 里打开目录索引location /files/ { alias /data/files/; autoindex on; autoindex_exact_size off; autoindex_localtime on; }autoindex on会让访问者看到文件列表网页可以像浏览下载站一样点击下载。不过公网环境建议别开autoindex加了认证和限速再考虑。4. 从单点走向集群反向代理和负载均衡4.1 upstream 块与常用负载均衡策略反向代理一次只能转发到一个后端地址负载均衡则是同时管理多个后端地址并分配流量。Nginx 用upstream块来定义一组后端服务器然后在proxy_pass里引用这组的名字upstream backend_pool { server 127.0.0.1:8080 weight3; server 127.0.0.1:8081 weight1; server 127.0.0.1:8082 down; keepalive 32; } server { listen 80; server_name app.example.com; location / { proxy_pass http://backend_pool; proxy_http_version 1.1; proxy_set_header Connection ; } }Nginx 默认使用轮询Round Robin策略请求依次打到 8080、8081、8080、8081……加weight3之后8080 被选中的概率是 8081 的三倍适合新服务器刚开始灰度、想多送点流量过去观察情况的场景。down标记表示这台服务器不参与负载比如它正在维护。如果业务依赖用户会话比如用户登录状态存在本地 Session不能随便换节点那就得用ip_hashupstream backend_pool { ip_hash; server 127.0.0.1:8080; server 127.0.0.1:8081; }ip_hash会基于客户端 IP 计算哈希保证同一个 IP 的请求每次都落到同一台后端从根本上解决 Session 漂移问题。它也有缺点如果某一台后端挂了哈希到该节点的用户会短暂受影响直到后续请求被重新分配。另一种更平滑的方案是least_conn它会让新请求优先分配给当前并发连接数最少的后端适合后端处理能力差异较大的场景。4.2 被动健康检查与故障转移很多人以为 Nginx 的反向代理天然具备健康检查能力其实“开箱即用”的是被动健康检查。Nginx 默认在请求转发失败后会尝试把请求转发给 upstream 里的下一台服务器这个行为由以下参数控制upstream backend_pool { server 127.0.0.1:8080 max_fails3 fail_timeout10s; server 127.0.0.1:8081 max_fails3 fail_timeout10s; }意思是 10 秒内如果这台后端失败次数达到 3 次Nginx 就把它标记为不可用并且在这 10 秒内不再把新请求转发给它。这种机制不需要额外的模块配置简单但它是“出事之后才知道”的被动模式。如果你需要周期性主动探测后端健康状态就需要 Nginx Plus 的商业模块或者使用官方开源的nginx_upstream_check_module补丁包。考虑到生产环境的可用性要求我个人的经验是Nginx 做基础故障转移就够了真正的精细化健康检查交给上层的服务治理框架比如 Spring Cloud 的注册中心、Kubernetes 的探针。不要试图让 Nginx 承担它不擅长的事层级清晰故障排查才不混乱。4.3 不止 HTTPstream 模块做四层反向代理Nginx 不仅支持 HTTP/HTTPS 反向代理还能通过stream模块做 TCP/UDP 的四层转发。常见的场景是 MySQL 集群、Redis 集群、MongoDB 数据库的访问入口统一收敛。什么意思呢假设你有三台 Redis分别跑在 10.0.0.3、10.0.0.4、10.0.0.5 上直接让业务方记住 IP 列表不现实改成让业务方统一连 Nginx 的 16379 端口Nginx 再把 TCP 流量转发到这三台 Redis。配置写在stream块中它和http块平级不能嵌套在 http 块里。示例stream { upstream redis_backend { server 10.0.0.3:6379; server 10.0.0.4:6379; server 10.0.0.5:6379; } server { listen 16379; proxy_pass redis_backend; proxy_timeout 30s; } }默认编译的 Nginx 可能没有stream模块确认方法很简单执行nginx -V查看编译参数里是否包含--with-stream。如果没有编译安装时就加上这个参数。要注意四层代理无法读取 HTTP 层信息所以做不了 URL 级别的路由也无法做 WebSocket 的 HTTP 升级它的优势是透明、高效适用于任意 TCP 协议。5. 进阶玩法SSL、WebSocket、缓存与安全加固5.1 配置 HTTPS 和 HTTP/2给反向代理入口加上 HTTPS是保护数据链路的第一道门槛。证书文件放在 Nginx 可读取的路径下一个带 SSL 的 server 块大致长这样server { listen 443 ssl http2; server_name api.example.com; ssl_certificate /etc/nginx/certs/api.example.com.crt; ssl_certificate_key /etc/nginx/certs/api.example.com.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto https; } }这里有两个关键点第一X-Forwarded-Proto必须设置为https后端框架才会正确识别用户是通过 HTTPS 访问的否则重定向生成 http 链接页面加载时浏览器会报不安全。第二listen 443 ssl后面追加http2现代浏览器就能启用 HTTP/2 多路复用实际体验是并发请求性能明显提升。如果你使用的是较新的 Nginx 版本http2指令已经并入listen参数这种写法是兼容的。5.2 WebSocket 反向代理升级头是关键WebSocket 比普通 HTTP 多了一次协议升级的过程。Nginx 默认情况下会剥离Upgrade和Connection头导致 WebSocket 握手失败。处理方式是在 location 里显式声明location /ws/ { proxy_pass http://websocket_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_read_timeout 3600s; proxy_send_timeout 3600s; }三行必配项是proxy_http_version 1.1、proxy_set_header Upgrade $http_upgrade;、proxy_set_header Connection upgrade;。$http_upgrade是 Nginx 内置变量它会原样透传客户端发来的 Upgrade 头。proxy_read_timeout 3600s是很多新手忽略的点WebSocket 连接建立后会长时间保持空闲如果超时时间还是默认的 60 秒一分钟后连接就被断开了前端会频繁重连表现就是“消息时不时丢了”。这套配置在聊天系统、协同编辑、实时通知项目里都能直接复用。如果你用了 uni-app 的 video 组件或者 WebSocket 类的应用部署到生产环境时记得检查这一步否则测试环境好好的一上服务器就走不通。5.3 静态资源缓存和访问控制反向代理经常也承担缓存功能。Nginx 可以把后端返回的静态资源缓存到本地磁盘减少后端压力。先定义缓存区proxy_cache_path /data/nginx/cache levels1:2 keys_zonestatic_cache:50m inactive7d max_size5g;再在 location 中使用location ~* \.(png|jpg|css|js|woff2)$ { proxy_cache static_cache; proxy_cache_valid 200 302 24h; proxy_cache_valid 404 1m; proxy_set_header Host $host; proxy_pass http://accessed; add_header X-Cache-Status $upstream_cache_status; }响应头里的X-Cache-Status可以看到命中情况HIT 表示缓存命中MISS 表示未命中这个调试信息非常有用。但缓存的坑也很明显后端更新了图片或 JS前端还是旧内容排障时首先确认proxy_cache_bypass和proxy_no_cache有没有配合设置以及版本号是否变化。一般我会对带版本号的静态文件开长缓存对 API 响应完全不开缓存避免数据不一致。5.4 限流、IP 白名单与安全头安全加固这块很多人容易到最后才想起来。Nginx 内置了limit_req模块可以针对单位时间内的请求频率做限制limit_req_zone $binary_remote_addr zoneapi_limit:10m rate5r/s; server { location /api/ { limit_req zoneapi_limit burst10 nodelay; proxy_pass http://backend_pool; } }rate5r/s表示每秒只能放行 5 个请求burst10表示允许瞬时最多 10 个请求排队nodelay则让排队请求不延迟。把限流配在登录接口、短信验证码接口前能挡住很大一部分暴力请求。IP 白名单则简单粗暴location /admin/ { allow 10.0.0.0/8; allow 192.168.1.100; deny all; proxy_pass http://admin_backend; }allow和deny按从上到下的顺序匹配命中allow就不再继续往下检查。这里要格外注意deny all必须放在最后否则会拦截所有来源。再加上常见的安全响应头比如X-Content-Type-Options、X-Frame-Options就能给整体安全加分。网络上常把这套机制称为“安全配置管理器”其实就是把各种防护用 Nginx 组合起来思路比工具本身更重要。6. 配置过程中最常踩的坑与排查方法6.1 端口占用导致启动失败Nginx 启动时报bind() to 0.0.0.0:80 failed (98: Address already in use)几乎每个新手都遇到过。原因要么是 Nginx 已经有一个 master 进程在运行要么是 Apache、Tomcat 或者其他 Web 程序占用了 80 端口。排查手段是先看进程再找端口ps -ef | grep nginx sudo lsof -i :80如果确实是 Nginx 自己残留的进程执行nginx -s stop或者sudo systemctl stop nginx再启动。如果是别的程序占用两种选择杀掉别的程序或者修改 Nginx 监听端口。Windows 下排查命令是netstat -ano | findstr :80看到 LISTENING 状态的 PID 后到任务管理器里核对进程身份。6.2 配置改了不生效先 test 再 reload很多人改完配置不执行任何命令直接刷新页面发现没变化就一脸雾水。Nginx 的配置只有在reload之后才会加载生效而且加载前一定要先做语法检查nginx -t如果输出syntax is ok和test is successful再执行 reload。如果配置有问题nginx -t会明确告诉你错误在第几行比浏览器里一片空白好排查得多。在include多文件场景下配置文件名有错、目录权限不对、末尾少了分号都会导致nginx -t报错。分号这一点特别常见一行配置忘记结尾分号后面的所有配置都会被解析成同一行报错位置可能离真实出错点很远。平时我建议养成一个固定习惯任何配置改动三步走——备份、nginx -t、nginx -s reload。到大型架构里会先从灰度环境验证再动生产环境道理一样只是规模放大。6.3 502 与 504 的排查路径502 Bad Gateway 很常见值就是 Nginx 已经启动但它找不到能转发的后端。排查顺序我固定如下先看后端进程是否存活再看后端端口是否监听成功然后用 curl 模拟请求看后端响应。例如curl -I http://127.0.0.1:8080/health如果 curl 能通Nginx 却 502问题多半出在 Nginx 配置文件里的proxy_pass地址写错了或者后端的 Host 校验不通过。如果 curl 不通那就是后端服务本身的问题去查应用日志。另一种情况是 504 Gateway Timeout意思是 Nginx 把请求转过去了但后端在规定时间内没返回。这时候调整proxy_read_timeout、proxy_connect_timeout时间同时排查后端是否有慢查询、死锁或者线程池耗尽的问题后者才是根因。6.4 日志是排障的第一现场“日志在手天下我有”这句话放在 Nginx 排障里再合适不过。默认错误日志在/var/log/nginx/error.log访问日志在/var/log/nginx/access.log。遇到问题先别急着猜打开错误日志看看sudo tail -n 100 /var/log/nginx/error.log sudo tail -n 100 /var/log/nginx/access.log错误日志里会记录启动失败的详细原因、SSL 证书路径问题、upstream 连接失败等。访问日志配合awk命令可以快速统计请求量、状态码分布awk {print $9} /var/log/nginx/access.log | sort | uniq -c | sort -rn把日志按天切割、定期归档是生产环境的基本要求否则日志文件越滚越大磁盘空间被占满时 Nginx 会拒绝写入新请求日志表现也是诡异的“不响应”。6.5 关于平滑升级的细节Nginx 的平滑升级是我见过最多人搞混的概念。很多人把nginx -s reload当成平滑升级其实 reload 只是重载配置二进制程序版本并没有变。真正的平滑升级是要替换 Nginx 可执行文件本身同时保证正在处理的请求不中断。常规做法是编译新版本到新路径然后通过发送信号让旧 master 优雅退出、新 master 接管。这个操作在生产环境可以做但风险也不小尤其是编译参数没保持一致时模块丢失的情况时有发生。我的建议是如果你的 Nginx 是系统包管理器安装的优先用系统的升级命令比如dnf update nginx或者apt upgrade nginx发行版已经把平滑升级的细节处理好风险低得多。只有当你必须使用自定义编译参数时才去手动做二进制替换并且一定要先在同样配置的测试机上演练一遍。7. 面试和晋升答辩里最常被问到的 Nginx 话题7.1 反向代理与正向代理的区别这是 Nginx 面试题的“必考项”。核心差异从流量方向就能讲清楚正向代理代理的是客户端隐藏客户端身份访问外部资源反向代理代理的是服务端隐藏服务端真实地址对外提供统一入口。两者都是代理但服务对象完全不同。举例说明最有说服力。员工通过公司正向代理访问外网外网网站看到的是代理服务器 IP不是员工本地 IP用户访问电商网站请求先进 Nginx 再进后端用户看到的只是 Nginx 的 IP内部服务器 IP 对外完全不可见。凡是想表达“我理解架构抽象层次”的时候用这个例子都能加分。7.2 Nginx 为什么能扛住高并发一个经常被问到的问题是“Nginx 高并发的原理是什么”。答案集中在事件驱动模型和多进程架构上。Nginx 启动后有一个 master 进程管理全局多个 worker 进程并行处理请求。每个 worker 采用基于 epoll 的事件驱动机制管理大量连接而不是像传统 Apache 那样每个连接派生一个进程或者线程。epoll 能够在大量连接中快速找出哪些是活跃事件让 Nginx 用相对很少的线程数支撑几十万并发连接。我还喜欢用食堂打饭类比传统模型是每个窗口有一个人专门服务一个学生人多就得开一堆窗口Nginx 的模式是一个窗口的服务员同时看着所有排队的学生谁有动静就先服务谁。同样的食堂面积能服务的人完全不同。7.3 Nginx 和 Apache 的核心差异互联网老前辈都知道 Apache 曾经统治 Web 服务器很多年但面对高并发场景Apache 的同步阻塞模型逐渐吃力Nginx 才以黑马姿态崛起。Nginx 的优势主要体现在内存占用低、静态文件处理性能强、反向代理和负载均衡的天然优势Apache 的优势则是模块生态极其丰富配置文件对开发者友好有大量.htaccess级别的目录级配置能力。今天很多项目其实两者并存Apache 负责内部传统业务Nginx 做统一入口各取所长。如果是面试里让我一句话回答我会说“Nginx 胜在高并发和反向代理上的优雅Apache 胜在功能和模块的全面。选型上如果追求性能和灵活度Nginx 几乎是更优解。”7.4 顺手写几个高频配置片段除了理论面试也经常让手写配置。最经典的就是“请配置一个反向代理把/api请求转发到http://127.0.0.1:8080”。我会顺手把 Host 头、真实 IP、超时时间一并写出来先把 80 端口监听好再配一个带 SSL 的 443 端口。其次是“如何配置负载均衡”直接写出带weight和ip_hash的 upstream 块。面试官看完基本就能判断你是不是真的敲过配置。这几个片段覆盖了日常大半需求写熟它们比背一堆理论有用。8. 最后分享一点我的实操体会我自己在多个项目里用过 Nginx从单机部署到多节点负载均衡从 HTTP 到 HTTPS 再到 WebSocket踩过的坑数都数不过来。要说最有价值的经验就是“配置能小则小”。很多教程给你一大段完整配置看得人头晕其实生产环境真正必需的指令就那么十几条。每加一条指令往前排查问题的复杂度就增加一分所以不要盲目复制别人有历史包袱的配置每多一个if多一个 rewrite都要想清楚它到底解决什么问题。另外建议大家学着把 Nginx 配置纳入版本管理从一个空目录开始每个业务一个文件文件名带清晰前缀改动前先备份改完先nginx -t。这套习惯比任何花哨工具都管用。遇到后端返回异常时记得第一时间看 Nginx 和后端两边的日志大多数“玄学问题”在日志面前都是纸老虎。希望这篇内容能帮你少走几步弯路把 Nginx 反向代理真正变成你顺手顺心的工具。
返回列表