ARTICLE DETAIL

资讯详情

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

Nginx反向代理从原理到实战:核心配置与调优指南

Nginx反向代理从原理到实战:核心配置与调优指南 1. 项目背景与核心需求拆解做 Web 开发和服务器运维的基本都绕不开 Nginx 这个名字。无论是给前端静态页面找个宿主还是给后端 Java、Python、Node 服务做一层转发网关Nginx 都是最趁手的那把刀。我自己从最早的 Apache 换到 Nginx再从单纯托管静态文件一步步玩转反向代理、负载均衡、灰度发布可以说 Nginx 反向代理这一块是每一个互联网从业者都该吃透的基本功。很多人第一次接触“反向代理”这四个字容易被绕进去。用大白话讲反向代理就是 Nginx 站在用户和真实服务器中间用户其实是在跟 Nginx 打交道真正干活的服务器躲在 Nginx 背后。用户请求过来Nginx 判断该往哪台服务器转再把服务器的响应原路返回给用户。整个过程中用户只认 Nginx 这一个“门面”根本不知道背后有几台服务器、服务器是什么语言写的、目录结构长什么样。反过来真实的业务服务器也不直接面对外网流量因此少了很多安全上的麻烦。作为一个多年一直在用 Nginx 的从业者我想在这篇内容里把反向代理从原理、配置、参数调优到实战坑点完整串一遍尤其针对搜“nginx 反向代理”时最常见的一些高频场景——比如部署前后端分离项目、给 Java 服务做网关、多域名共用一个 Nginx、WebSocket 长连接代理、以及 HTTPS 证书配置——做一个偏工程向的实操拆解。这篇文章适合刚接触 Nginx 的开发者和运维新手也适合那些已经在用基础转发、但想搞清楚 proxy_pass 路径拼接、负载均衡策略、head 里面那些 header 到底要不要带的人。2. Nginx 反向代理的整体设计与选型思路2.1 为什么要用 Nginx 做反向代理而不是别的方案先回应一个很自然的问题现在微服务网关有 Spring Cloud Gateway、有 Kong、有 Traefik为什么还要学 Nginx我的答案是——Nginx 才是那个什么时候都跑不掉的底座。Nginx 的高性能是出了名的。在高并发场景下Nginx 采用异步非阻塞的事件驱动模型一个 worker 进程可以同时处理海量连接对于大多数中小型业务来说Nginx 作为流量入口完全扛得住。而且 Nginx 的定位非常清晰它就是做代理和静态资源服务的不会像业务服务一样被复杂的业务逻辑拖累。一个纯转发层稳定性必然是第一位的。从部署成本看Nginx 的安装和配置极其轻量编译出一个可执行文件不过几 MB 级别。相比 Java 系的网关动辄要引入全家桶依赖、还要考虑 JVM 内存、配置中心、注册中心Nginx 的落地成本低到可以忽略。很多公司即便上了微服务网关也依然习惯在最外层挂一个 Nginx 做 SSL 终结、做静态资源边缘缓存、做基础的流量分发网关只负责内部的服务路由逻辑。还有一个很现实的原因Nginx 的生态兼容性太好了。Linux、Windows、macOS 都能用和前后端分离项目的配合是天作之合对 HTTPS 证书的支持干净利落和 Docker、Kubernetes 里的 Ingress Controller 也有直接血缘关系。学会了 Nginx 反向代理等于同时掌握了云原生网关的底层逻辑这笔投入绝对不亏。2.2 反向代理的工作模型与核心流程从请求链路看反向代理的角色可以拆成四个环节接收、识别、转发、回传。用户发起一个 HTTP 请求到 Nginx 监听的端口Nginx 根据请求的 host 头、URL 路径、甚至请求头里的某些字段来决定将该请求交给哪个上游服务器处理。这个“决定”的过程就是 Nginx 配置里面层层匹配的规则。匹配完成后Nginx 建立到上游服务器的连接把请求原样转发过去。上游处理完返回响应Nginx 再把响应传回给客户端。注意这个过程中Nginx 可以选择缓冲上游响应也可以选择边收边发proxy_buffering off这在后面讲实时性场景时会用到。对比正向代理反向代理最大的区别在于代理对象不同。正向代理是替客户端去访问外部资源客户端知道目标在哪但目标不知道真实客户端是谁反向代理则是替服务器接收流量客户端知道入口在哪但不知道真实的服务器在哪。理解了这两者的差异就能明白为什么反向代理天生适合做负载均衡和统一入口。2.3 为什么优先推荐源码编译安装不少新手图省事直接用yum install nginx或者apt install nginx这当然可以跑但我个人在需要深度定制、需要连接最新版本模块、或者要处理特殊优化参数时更推荐源码编译安装。编译安装的好处是你可以自己决定开启哪些模块比如--with-http_ssl_module、--with-http_realip_module、--with-http_stub_status_module等还能加上 C 编译器的优化参数比如-O2让运行效率更高。不过话说回来如果你的内核和系统源里带的 Nginx 版本不算太老也没有模块需求直接用包管理器装是最省事的。判断方式很简单跑nginx -V看看编译参数如果带--with-http_ssl_module和--with-http_v2_module那日常反向代理基本够用。等需要加模块了再走一遍编译安装或者平滑加载动态模块也不迟。3. 核心配置拆解从 location 匹配到 proxy_pass 的路径学问3.1 location 匹配规则的优先级配置 Nginx 反向代理最核心的就是 location 块。location决定了哪些 URL 会被哪些规则接住再接住之后怎么处理。Nginx 的 location 匹配有一套优先级体系网上很多教程讲得云里雾里我用一句话概括精确匹配 前缀最长匹配 正则匹配按书写顺序 普通前缀匹配。具体规则拆开看location /api是精确匹配只匹配/api这一个路径优先级最高。location ^~ /static/是前缀匹配一旦命中就不再继续检查正则优先级仅次于精确匹配。location ~ /api/和location ~* /api/是正则匹配~区分大小写~*不区分。location /api/是普通前缀匹配如果多个普通前缀都匹配上取最长的那一个。最容易踩的坑是正则匹配和无修饰符前缀匹配的优先级问题。我见过不少人在同一个 server 里既写了location ~ \.php$又写了location /api结果/api/index.php这样的请求被 PHP 正则接走了后端直接给你返回 404。原因就是正则匹配的优先级高于普通前缀匹配。如果你想强制某个前缀路径不被正则抢走得用^~。3.2 proxy_pass 带不带斜杠结果天差地别location 匹配规则清楚了下一个高频出错点就是 proxy_pass 的 URL 末尾是否带斜杠。这个问题面试考过实战也坑过无数人。先记住两条最基础的结论location /api/配合proxy_pass http://backend;不带路径的部分转发时会保留原始 URI也就是/api/xxx整个路径都被传过去。location /api/配合proxy_pass http://backend/;带斜杠会替换匹配到的 location 前缀。比如客户端请求/api/user/list转发给后端的实际路径是/user/list。为什么会有这个区别因为 Nginx 拼接转发路径的逻辑是如果 proxy_pass 的 URL 中不带 URI即协议主机端口后直接结束那就把客户端完整的原始请求 URI 追加到后面如果 proxy_pass 带了 URI哪怕只有一个/那么匹配 location 的那一段前缀会被替换成 proxy_pass 里写的 URI 部分。这个特性在实际项目中非常重要。很多前后端分离的项目前端请求/api开头的接口后端服务的 context-path 是/那你的 location 就得写成/api/配合不带的 proxy_pass才能保证后端收到的还是/api/xxx后端如果配置了全局前缀匹配也能正常处理。反过来如果后端接口本来就包含/api前缀但服务里写死了路径你可能需要把 API 前缀剥掉再往后端转那就要在 proxy_pass 末尾加/。3.3 反向代理必须带上的 header 三件套只做最简单的 proxy_pass 转发很多场景下接口能通但拿到线上就各种问题——最典型的就是用户真实 IP 丢失、Host 信息错误、以及 HTTPS 跳转无限循环。这一节我把必须手动配置的 header 三件套拉出来每一个都知道为什么要加。第一个是Host。Nginx 默认转发时传给后端的 Host 头是 proxy_pass 里配置的 IP 或域名而不是用户原始请求中的域名。如果你的后端服务绑定了域名白名单或者根据 Host 做多租户判断那就必须显式带上proxy_set_header Host $host;。用了这个配置后端看到的 Host 就是用户访问时的域名。第二个是X-Real-IP带上真实客户端 IP。不加这个 header后端所有请求日志里的 IP 全是 Nginx 的 IP查问题、做限流、做风控全废。配置方式是proxy_set_header X-Real-IP $remote_addr;。如果你的项目里还需要完整的链路 IP 信息或者 Nginx 前面还有一层负载均衡那就要用X-Forwarded-For格式类似于每次经过一层代理就追加上一层看到的客户端地址proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;第三个是X-Forwarded-Proto。当 Nginx 作为 SSL 终结节点后端是 HTTP 时后端服务需要知道用户原本是用 HTTPS 还是 HTTP 访问的。尤其要注意很多应用在生成绝对路径的跳转链接或者 OAuth 回调地址时会读这个头。如果不加后端以为自己是 HTTP 服务就会生成http://的链接导致浏览器报“不安全”或跳转丢失。配置proxy_set_header X-Forwarded-Proto $scheme;4. 反向代理实战多场景配置与核心参数调优4.1 场景一前后端分离项目的一站式反向代理现在的主流 Web 项目基本都是前后端分离前端静态文件由 Nginx 直接托管后端 API 通过反向代理转发到 Java 的 Tomcat、Spring Boot 内嵌服务、或者 Python 的 Gunicorn 上。一个典型配置长这样server { listen 80; server_name www.example.com; # 前端静态资源直接由 Nginx 托管 location / { root /data/www/dist; index index.html; try_files $uri $uri/ /index.html; } # 后端 API 反向代理 location /api/ { 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; } }try_files $uri $uri/ /index.html;这行是给 Vue、React 这类单页应用用的。前端路由由 JS 控制服务端没有对应的物理文件路径所以当用户直接刷新/user/profile时Nginx 找不到这个路径就回退到根目录的index.html让前端框架自己接管路由。这一行如果不写刷新页面就会得到 404。我见过无数同事在部署前端项目时卡在这一步后来形成条件反射了看到单页应用脑子里自动跳出这行配置。4.2 场景二WebSocket 长连接代理如果后端服务用到了 WebSocket比如在线聊天、消息推送、协同编辑Nginx 默认配置是转发不了的。WebSocket 协议升级需要 HTTP 请求头里的Upgrade和Connection字段而 Nginx 默认会忽略这两个头的转发。所以必须单独给 WebSocket 的 location 写一套配置location /ws/ { proxy_pass http://backend_ws; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; 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_read_timeout 3600s; proxy_send_timeout 3600s; }Connection upgrade是固定的写法用于告知上游这个连接要升级成 WebSocket 长连接。proxy_http_version 1.1也很重要WebSocket 握手依赖 HTTP/1.1 的持久连接特性。还有一个细节是超时时间。WebSocket 连接的特点是长时间不通信如果 Nginx 默认的proxy_read_timeout是 60 秒那么 60 秒内客户端没有发送任何消息Nginx 就会主动断开连接。所以要对 WebSocket 的 location 单独设置较大的超时时间这个时间最好跟后端心跳机制配合比如心跳是 30 秒一次超时设 3600 秒就非常稳妥。4.3 场景三代理外部 HTTPS 接口如 OpenAI 类服务现在很多开发者习惯用 Nginx 代理外部 API 服务典型的就是把某个海外接口基于合规的访问需求通过一个统一网关转发出去。这类场景要处理的核心是 HTTPS 证书信任和 SNI 问题。server { listen 80; server_name api.example.com; location / { proxy_pass https://api.someprovider.com; proxy_ssl_server_name on; proxy_set_header Host api.someprovider.com; proxy_set_header X-Real-IP $remote_addr; proxy_ssl_protocols TLSv1.2 TLSv1.3; } }proxy_ssl_server_name on的作用是让 Nginx 在向上游发起 TLS 握手时携带 SNIServer Name Indication字段也就是告诉上游服务器“我要访问的域名是哪个”。如果不加某些 CDN 或云服务商的多域名共用一个 IP 时会直接拒绝连接。另外如果你和后端服务之间经过自签证书或非标准证书链路可能需要设置proxy_ssl_verify off但强烈不建议在生产环境这么做这会放弃 TLS 链路验证。安全底线还是得有。4.4 场景四一个 Nginx 部署多个网站主域名 二级域名通过 Nginx 的server_name做多域名区分是最常见的虚拟主机玩法。比如主域名 www.example.com 挂官网二级域名 admin.example.com 挂管理后台api.example.com 挂接口服务。只需要在一个 http 块里配置多个 server 块即可。server { listen 80; server_name www.example.com example.com; root /data/www/site; } server { listen 80; server_name admin.example.com; location / { proxy_pass http://127.0.0.1:8081; } } server { listen 80; server_name api.example.com; location / { proxy_pass http://127.0.0.1:8082; } }这里要特别注意server_name的匹配优先级精确匹配 通配符前缀匹配*.example.com 通配符后缀匹配example.* 正则匹配。如果同一个请求匹配到多个 serverNginx 会按这个优先级顺序选择。因为这种特性有时候你会在配置里写一个default_server来兜底所有没匹配上的请求。比如listen 80 default_server;配了 default_server 的那个 server 会成为默认接收者所有未命中的请求都会进到这个配置里。这样能避免有人直接拿 IP 访问你的服务器时意外访问到某个业务页面。4.5 场景五HTTPS 证书配置与强制跳转给 Nginx 配 HTTPS 说难不难关键是证书链完整性和重定向逻辑。常规套路server { listen 443 ssl; http2 on; server_name www.example.com; ssl_certificate /etc/nginx/ssl/example.com.pem; ssl_certificate_key /etc/nginx/ssl/example.com.key; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; keepalive_timeout 70; 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; } } server { listen 80; server_name www.example.com; return 301 https://$host$request_uri; }常见问题有两个。第一个是证书链不完整浏览器提示“证书不受信任”。解决方法是把证书文件拆开看确保证书内容从站点证书开始中间证书、根证书按顺序拼在一起。很多证书提供商会直接给一个 fullchain.pem把这个文件配给ssl_certificate就行。第二个问题是在配置强跳转 80 到 443 后发现后端接口返回的连接还是 HTTP多半是X-Forwarded-Proto没配或者 Spring 这类框架对 forwarded 头理解不到位需要额外配置 forward-headers。这一点前面已经提过但还是要强调X-Forwarded-Proto在 HTTPS 场景下真的能救命。4.6 负载均衡与健康检查配置反向代理最常见的进阶玩法就是负载均衡。Nginx 通过upstream块定义一组后端服务器然后 proxy_pass 指向这个 upstream 名称。upstream backend_cluster { least_conn; server 192.168.1.10:8080 weight3 max_fails3 fail_timeout30s; server 192.168.1.11:8080 weight1 backup; keepalive 32; } server { listen 80; server_name api.example.com; location / { proxy_pass http://backend_cluster; proxy_set_header Host $host; } }这里的策略配置非常实用默认是轮询round-robin每个请求按顺序轮流分发。least_conn会将新请求发给当前活跃连接数最少的后端适合处理长请求、慢接口不均匀的场景。weight用来做权重分配比如新机器刚上线可以暂时给低权重观察稳定性后再调高。backup标记的服务器只在所有非备份节点不可用时才会被启用适合做冷备。max_fails和fail_timeout控制健康检查逻辑。比如max_fails3 fail_timeout30s表示后端连续失败 3 次后Nginx 在 30 秒内不再往这个节点发请求。很多人容易忽略keepalive的作用。默认 Nginx 向后端发请求是短连接每次都要重新建 HTTP 连接性能和延迟都有损耗。配了keepalive 32之后Nginx 会和上游服务器保持一批空闲长连接复用连接转发请求。尤其在高 QPS 场景下这个优化效果非常明显。要启用这个特性还必须配proxy_http_version 1.1;和proxy_set_header Connection ;否则 keepalive 连接池不会生效。4.7 缓存、缓冲与超时参数调优反向代理不只是转发几个高频调优点直接影响用户体验和服务器稳定性。proxy_buffering默认是 on意味着 Nginx 会先把后端的响应全部收完再统一返回给客户端。这么做的好处是后端响应慢时Nginx 不会把慢速客户端和后端服务直接绑死而是自己做一个缓冲降低后端的并发压力。坏处是像 Server-Sent Events、流式输出这类场景客户端希望数据一到就立刻看到缓冲反而破坏了实时性。所以流式场景要显式关闭proxy_buffering off;proxy_buffer_size控制 Nginx 接收后端响应头部的缓冲区大小默认一般是 4k 或 8k。如果后端返回的 Cookie 很长、响应头特别大而缓冲区不够Nginx 会返回 502 或者“upstream sent too big header”错误。常见解法是调大proxy_buffer_size 16k; proxy_buffers 8 16k;proxy_connect_timeout默认 60 秒定义 Nginx 与后端建立 TCP 连接的超时时间。内网服务一般 5 秒到 10 秒足够公网链路不稳定时可以放宽到 30 秒。proxy_read_timeout默认也是 60 秒定义后端处理完并返回数据的最大等待时间。业务接口偶尔会有长耗时比如导出报表跑 3 分钟那就必须把proxy_read_timeout调到 300 秒以上否则 Nginx 会在 60 秒后强断连接。这类问题出现时后端日志里没任何报错但客户端看到 504原因就在这里。5. 安全加固与权限边界5.1 隐藏版本号与基础加固Nginx 默认会在 HTTP 响应头里带上Server: nginx/1.18.0这样的版本信息。攻击者可以据此搜索对应版本的历史漏洞。隐藏版本号的办法server_tokens off;这只是一个态度问题真正的加固还要从访问控制和请求体限制做起。下面这段配置属于基础安全基线# 限制单个请求体大小防止大文件上传拖垮后端 client_max_body_size 10m; # 拒绝非法的 HTTP 方法 if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE|OPTIONS)$) { return 444; } # 限制浏览器访问某些敏感路径 location ~ /\.(git|svn|env|htaccess) { deny all; }return 444是 Nginx 的非标准返回码收到这个指令后 Nginx 直接关闭连接不给任何响应内容比返回 403 更节省资源也是很多安全加固方案的常规操作。5.2 反向代理层防御常见攻击如果你是用 Nginx 代理到公网服务或者代理层本身暴露在公网建议至少考虑两层防护。第一层是限流。Nginx 自带的limit_req模块可以做请求速率限制。比如限制每个 IP 每秒只能请求 10 次limit_req_zone $binary_remote_addr zoneapi_limit:10m rate10r/s; location /api/ { limit_req zoneapi_limit burst20 nodelay; proxy_pass http://backend; }rate10r/s表示每秒 10 个请求。burst20表示允许短时间突发 20 个请求排入队列但不阻塞超出的直接拒绝。nodelay表示突发请求排队时不额外增加延迟等待时间。第二层是访问控制。基于 IP 白名单的写法location /admin/ { allow 192.168.1.0/24; allow 127.0.0.1; deny all; proxy_pass http://admin_backend; }对于管理后台这类敏感服务IP 白名单是最直接的管控手段。记住allow和deny是顺序执行的先匹配先生效。所以白名单写前面deny all兜底。6. 常见问题排查实录与面试高频点6.1 502 Bad Gateway 问题排查这是反向代理里出现频率最高的错误。出现 502说明 Nginx 和后端之间的通信出问题了。排查套路按下面几步走第一步确认后端进程还活着。ps -ef | grep java或者curl 127.0.0.1:8080/health如果后端连不上自己先解决后端问题。第二步看防火墙。内网环境经常是后端服务监听了 127.0.0.1 而不是 0.0.0.0Nginx 转发到这台机的公网 IP 或容器 IP 时会被拒。用ss -lntp看监听地址确保监听的是 Nginx 能访问到的地址。第三步看 Nginx 的错误日志/var/log/nginx/error.log。如果看到connect() failed (111: Connection refused)说明端口没通如果看到connect() timed out说明网络不通或者后端负载过高。第四步检查proxy_pass配置的上游端口和实际端口是否一致。我见过最隐蔽的一次 502是后端服务启动正常日志也正常但 Nginx 就是连不上。后来发现后端服务监听的 IPv6 地址Nginx 用 IPv4 去访问自然连接被拒。解决方式是让后端监听0.0.0.0:8080而不是::。6.2 504 Gateway Timeout504 和 502 不同TCP 连接建立了但后端迟迟没有返回完整响应。优先考虑proxy_read_timeout太短。自己写接口测一下后端处理耗时如果后端要 90 秒你设 60 秒就必然 504。其次考虑后端线程池被打满连接虽然能建上但一直排队得不到处理。这种情况后端日志会有线程池拒绝的报错需要调大连接数和线程数。还有一种情况是后端处理中产生了死锁或长时间 GC这种需要结合后端监控一起来定位。还有一个容易忽略的点如果 Nginx 开启了proxy_buffering off而客户端下载断开了Nginx 会把错误信息传给后端导致后端写 socket 报错。排查时能看到 upstream 日志里有client prematurely closed connection别慌先查客户端行为再查后端。6.3 404 与路由丢失问题出现转发后 404大概率是proxy_pass路径拼接不对。比如 location 是/apiproxy_pass 是http://backend/那么请求/api/users转后变成/users如果后端路由里预期收到的是/api/users自然就 404。这类问题的排查方式很简单在后端日志里看接收到的实际请求路径是什么对比预期即可。如果是前端刷新页面 404而不是接口 404那就是try_files没配置回到单页应用那节把try_files $uri $uri/ /index.html;加上。6.4 高频面试题整理结合反向代理这个主题我在面试候选人的时候喜欢问以下几个问题这里也一并梳理答案给准备跳槽的朋友参考问题 1Nginx 反向代理和正向代理有什么区别正向代理代理的是客户端反向代理代理的是服务端。正向代理中客户端知道目标服务器但目标服务器不知道真实客户端是谁反向代理中客户端不知道真实服务器是谁只认识 Nginx 这个网关。问题 2proxy_pass 末尾带/和不带/有什么区别不带/时客户端请求的完整 URI 会原样传给后端带/时location 匹配到的前缀会被替换成/。这个之前展开过面试时直接举例子说明即可。问题 3如何获取用户的真实 IP配置proxy_set_header X-Real-IP $remote_addr;和proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;后端从请求头里取。但要提醒如果 Nginx 前面还有负载均衡器或 CDN单靠一层 Nginx 配置还不够要保证链路每一层都正确追加 X-Forwarded-For并且最外层要过滤掉伪造的 XFF 头。问题 4Nginx 中 location 的匹配优先级是什么精确匹配然后是^~前缀匹配然后是正则~/~*最后是普通前缀匹配取最长前缀。正则按书写顺序命中即停。问题 5反向代理时为什么要配 proxy_set_header Host $host默认 Nginx 转发后端时带的是 upstream 的 IP 端口后端如果需要基于域名做路由、生成重定向 URL、校验 Host 白名单都会出问题。这也是很多应用转发后登录跳转异常的根因。6.5 Nginx 平滑升级与版本漏洞处理维护 Nginx 最需要留心的就是版本漏洞。像以往曝出的 CVE 里就出现过利用Content-Length或Range请求头绕过访问控制的高危漏洞。作为维护者你至少要能熟练完成平滑升级和快速回滚。Nginx 平滑升级的原则是启动新版本二进制保留旧的 master 进程和 worker 进程处理存量连接新连接交给新进程。传统手法是给旧 master 发 USR2 信号让它拉起新 master然后再发 WINCH 信号逐步关闭旧 worker。现在官方推荐用二进制替换 nginx -s reload的方式大多数发行版下也是这个思路。在升级前先备份当前可执行文件cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak然后用新版本编译安装安装完成后先测配置/usr/local/nginx/sbin/nginx -t确认无报错后执行平滑重载/usr/local/nginx/sbin/nginx -s reloadreload 过程会重新加载配置创建新的 worker 进程旧的 worker 在完成存量连接后退出。如果升级后发现异常把备份文件换回去再 reload 一次即可。这里强烈建议加一个定时提醒nginx -V出来的版本号要去官网或者安全公告里核对是否存在已知 CVE。Nginx 的版本迭代并不频繁但一有版本就是安全相关别拿生产环境开玩笑。7. 一点实践经验总结踩过足够多的坑之后我对 Nginx 反向代理有几点很深的体会。配置一定要保持最小化。能在一个 location 里解决的问题就不要拆成两个能用默认参数跑通的场景就不要为了“优化”去改那些看不懂的参数。Nginx 的很多默认值是非常保守且经过验证的乱调参数反而容易引入诡异的问题。日志是最有用的排障工具。给反向代理的 location 里加上自定义日志格式比如记录$upstream_addr实际后端地址、$upstream_response_time后端响应耗时、$upstream_status后端返回码出了问题看日志一眼就能定位瓶颈。比如一条请求响应时间 3 秒但$upstream_response_time是 5 秒说明时间全耗在 Nginx 内部处理或客户端传输上如果$upstream_response_time本身就是 5 秒问题就直接定位到后端了。这个经验是真的能救命。配置文件的变量和 include 要善用但别滥用。多站点场景下把每个站点的 server 配置独立成一个文件放到 conf.d 下面按域名命名例如conf.d/api.example.com.conf找起来非常清爽。全局通用的 header 配置抽到一个 proxy_params 文件里每个需要代理的 location include 一下避免重复粘贴 20 行配置。不过 include 多了以后也要留意层级关系别嵌套太深否则维护成本反而上去了。最后聊一下测试。改完 Nginx 配置一定不要直接 reload 到生产先用nginx -t校验语法再在预发环境验证路径匹配和 header 透传是否符合预期。用 curl 带-H Host: xxx模拟不同域名的请求用curl -v看响应头和重定向这些都是最朴素的验证方式但足够有效。Nginx 反向代理这个主题说深可以很深说浅也真的很浅。掌握了 location 匹配规则、proxy_pass 路径拼接、header 透传、超时和缓冲参数调优这几板斧日常绝大部分场景都不会再有难住你的地方。剩下那些机制层面的细节比如 epoll 模型、共享内存、lua 扩展、动态 upstream 模块等你在实际业务里遇到瓶颈再去深挖反而记得更牢理解也更透彻。
返回列表