
搞Web开发的人迟早都要跟Nginx反向代理配置打交道。我自己接手过一个老项目的维护工作光梳理Nginx配置就花了一整天——里面堆了四五个server块location嵌套了好几层有的转发到内网Tomcat有的代理到外部地图服务还有一个负责前端静态资源。边看边改的过程中踩了不少坑也把Nginx反向代理这个知识盲区彻底补上了。这篇文章我就把Nginx反向代理配置这件事从头到尾捋一遍它到底解决什么问题、Nginx怎么装、核心配置每行什么意思、几个实战场景怎么落地、以及最常见的报错和排查思路。适合刚接触Nginx的后端、前端同学也适合部署踩坑之后回来查资料的运维新手。我尽量少讲抽象理论多给可以直接抄作业的配置和实测经验。1. 反向代理到底在解决什么问题1.1 反向代理的本质前台帮你转接你可以把反向代理理解为公司的前台。外部来访者不需要知道要找的人具体坐在哪个工位只要把需求递给前台前台根据情况分给相应的部门。对应到技术上客户端发请求到NginxNginx按照规则转发给后端的某个服务再把后端返回的结果带回给客户端。整个过程对客户端是透明的客户端始终只认识Nginx这一个入口。在没有反向代理之前服务端架构是“一对多直接暴露”每个后端服务都得有独立的域名或端口客户端需要知道具体的host、端口、路径。一旦后端服务迁移、扩容、加鉴权客户端也得跟着改维护成本非常高。有了反向代理之后客户端只管访问一个统一入口后端怎么变都由Nginx在内部消化。这一点在微服务和小型集群里特别重要。比如我原来维护的项目后端同时有Java接口服务、Python定时任务管理面板、Node.js的推送服务如果不做反代用户得记住三个端口而且跨域问题也会头疼。用Nginx统一代理之后外部只看到80端口内部的三个服务各自躲在后面安全性和可维护性都好了不少。1.2 正向代理与反向代理别搞混面试和日常讨论里最容易混淆的就是“正向代理”和“反向代理”。一句话区分正向代理是代理客户端反向代理是代理服务端。正向代理的场景最典型的是公司内网统一上网出口。用户不能直接访问外网先请求公司代理服务器由代理服务器去访问目标网站再把内容传回来。这个代理服务器代表的是用户目标服务器看到的是代理的IP不知道真实用户是谁。反向代理则反过来用户访问的是NginxNginx代表的是后端服务。用户根本不知道后端真实服务器在哪只知道Nginx的地址。我用一个表格把两者的关键差异列清楚对比项正向代理反向代理代理对象客户端服务端使用者客户端配置知道代理的存在客户端无感不知道反向代理存在典型场景内网上网出口、访问受限资源负载均衡、统一入口、动静分离、SSL终止代表技术Squid、HTTP ProxyNginx、HAProxy、Apache mod_proxy客户端感知客户端需要手动配置代理客户端只访问目标域名/端口明白了这个区别你在配置Nginx时就不会把它理解成“给用户开代理”而是“替后端服务接客”。1.3 为什么挑Nginx而不是Apache、Caddy市面上能承担反向代理的软件不只Nginx一个Apache有mod_proxyCaddy配置更简单HAProxy在负载均衡领域也很强。我之所以长期用Nginx是因为它在性能、配置灵活度和生态成熟度之间取了一个很好的平衡。Nginx采用事件驱动的异步架构一个worker进程可以同时处理成千上万个连接内存占用比Apache的进程/线程模型低很多。同样是扛几万并发Nginx对服务器资源的要求明显更低。配置方面Nginx的配置文件虽然语法稍显啰嗦但逻辑清晰server、location、upstream这些块级指令分层明确改起来不容易出错。而且Nginx模块生态非常成熟负载均衡、SSL终止、反向代理、缓存、限流、gzip压缩都能在一个配置文件里搞定不需要额外装一堆插件。Caddy的自动HTTPS确实方便但遇到复杂的URI改写、多条件判断、灰度发布这种场景表达能力反而不如Nginx直接。HAProxy在四层和七层负载均衡上性能极佳但静态资源服务、URL重写、和Web应用层的深度联动就不是它的强项了。所以我的结论是把Nginx作为默认的反向代理方案配合上负载均衡和静态资源托管绝大多数项目都够用了。2. 先把Nginx装好Windows与Linux实操2.1 Windows下跑起来解压就能用很多本地开发和测试场景需要在Windows上先跑一个Nginx。Nginx在Windows上不需要安装下载zip包解压即用。去Nginx官网下载Windows版本解压到一个比较干净的路径下比如D:\nginx-1.26.2。注意路径里不要有中文和空格虽然现在不少情况也能跑但遇到奇怪的相对路径报错你会后悔的。启动方式是在解压目录下执行start nginx或者直接双击nginx.exe。启动后打开任务管理器正常应该看到两个nginx进程一个master进程管理进程和一个worker进程实际处理请求。如果只有一个进程说明启动可能失败了可以去logs/error.log里看原因。验证是否启动成功在浏览器访问http://localhost看到“Welcome to nginx!”页面就说明没问题。我踩过的坑是Windows的80端口被其他程序占用。常见嫌疑犯包括IIS、SQL Server Reporting Services、VMware的HTTP服务、以及各种开发工具的本地调试服务器。查看端口占用用netstat -ano | findstr :80找到占用进程后在任务管理器里结束或者直接改Nginx配置里的监听端口。Windows下修改完配置文件用nginx -s reload就能生效不需要重启整个服务这点和Linux是一致的。2.2 Linux下安装包管理器与编译安装Linux服务器上安装Nginx通常有两种思路用系统包管理器安装或者源码编译安装。前者省事后者灵活。如果你用的是AlmaLinux、CentOS、Rocky Linux这类RHEL系发行版系统自带的基础源里可能没有Nginx需要先启用EPEL源。配置好EPEL源之后执行dnf install nginx安装完用systemctl start nginx启动设为开机自启用systemctl enable nginx。Ubuntu/Debian系更简单直接apt install nginx安装完成后服务一般会自动启动。包管理器安装的Nginx配置文件结构很规整/etc/nginx/nginx.conf是主配置/etc/nginx/conf.d/下放自定义的站点配置/etc/nginx/sites-available/和sites-enabled/在Ubuntu上用来管理站点启用和禁用。我习惯把每个项目单独建一个conf文件放在conf.d/目录下文件名用项目名命名例如myproject.conf方便日后维护。包管理器安装的优点是升级方便、配置目录规范、可以和systemd无缝集成。缺点是默认编译的模块不一定满足你的需求比如你需要在Nginx里做sub_filter内容替换、想用--with-http_v2_module关闭HTTP/2或者打算集成第三方模块如Lua、Brotli压缩这些都是系统包默认不带的。这时候就得考虑源码编译。2.3 编译安装与平滑升级源码编译安装Nginx核心步骤是先准备好依赖库再./configure生成Makefile然后make make install。以RHEL系发行版为例需要提前安装gcc、pcre-devel、zlib-devel、openssl-devel这几样东西分别对应编译工具、正则表达式库、压缩库、TLS加密库。下载Nginx源码包并解压后执行编译配置下面是常用参数./configure \ --prefix/usr/local/nginx \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_sub_module \ --with-http_gzip_static_module \ --with-stream make make install编译安装的二进制文件在/usr/local/nginx/sbin/nginx配置文件在/usr/local/nginx/conf/nginx.conf日志在/usr/local/nginx/logs/。和包管理器版本相比需要自己写systemd服务文件才能用systemctl管理不过网上有现成模板复制改改就行。再提一个王炸功能平滑升级。Nginx支持在不停机的状态下替换二进制文件实现版本升级。具体流程是下载新版本源码编译出新的nginx二进制备份旧二进制执行make upgrade或者手动方式——发送USR2信号让旧master启动新master再发WINCH让旧worker逐渐退出。我实测下来还是用make upgrade最省心两条命令就完成升级连接不中断。这个技能在处理Nginx安全漏洞需要紧急升级时非常有用。2.4 基本管理与验证命令不管哪种安装方式以下命令都是日常高频使用的我直接汇总成一张速查表。命令作用使用频率nginx -t校验配置文件语法输出ok和successful即通过每次改配置后必用nginx -s reload重新加载配置不停机日常改配置后nginx -s stop快速停止服务较少nginx -s quit优雅停止处理完当前请求再停较少systemctl start/stop/restart nginxsystemd管理服务配systemd后推荐systemctl status nginx查看服务运行状态排查时常用nginx -T输出最终生效的完整配置排查配置问题时推荐我个人的习惯是每次修改配置文件后先执行nginx -t校验语法再执行nginx -s reload生效。这个习惯帮我避免过好几次“改完配置忘了reload线上还在跑旧配置”的尴尬情况。3. 核心配置逐段拆解3.1 nginx.conf的整体目录结构Nginx的配置文件通过指令块分层组织。最外层是main块设置全局参数events块配置事件驱动模型http块封装所有HTTP相关的配置http块里可以定义多个server虚拟主机server里可以定义多个locationURI匹配规则。剥掉注释之后一个最简配置长这样user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; events { worker_connections 10240; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; server { listen 80; server_name example.com; location / { root /usr/share/nginx/html; index index.html; } } }worker_processes auto值得说一句它让Nginx根据服务器CPU核心数自动启动对应数量的worker进程。以前老配置喜欢手动填4、8之类的数字其实auto在大多数场景下最合理。worker_connections表示每个worker能同时打开的连接数上限默认1024太小压测时容易突破上限调到10240是常见做法。3.2 location匹配规则解析反向代理配置的重头戏基本都在location块里。location的作用是告诉Nginx当请求的URI满足某种匹配规则时执行块内的处理逻辑。理解匹配规则你才能准确控制哪些请求转给后端哪些请求直接返回静态文件。Nginx的location匹配优先级从高到低是location /path精确匹配完全相等才命中优先级最高。location ^~ /prefix前缀匹配一旦命中就不再检查正则。location ~ /正则/、location ~* /正则/i正则匹配按配置文件中的顺序执行第一个匹配到的生效。location /prefix普通前缀匹配匹配到后继续检查正则正则优先。举个例子用户请求/api/user/info配置里有location /api/和location ~ \.php$两者都能匹配时正则的优先级更高会走php处理逻辑。想强制某个前缀优先就用^~。我建议刚上手的人不要一上来就堆一堆正则。先写普通前缀匹配比如location /api/代理后端、location /static/走本地目录把基础路径理清楚之后再逐步引入正则。正则写多了匹配优先级一旦搞混排查一个404能折腾半天。3.3 proxy_pass带不带斜杠的区别proxy_pass是反向代理的核心指令语法很简单proxy_pass http://目标地址;。但有一个细节特别容易坑人目标地址结尾带不带斜杠直接决定了转发给后端的URI长什么样。不带斜杠时Nginx会将客户端请求的原始URI完整传给后端。举例location /api/ { proxy_pass http://127.0.0.1:8080; }客户端请求/api/user/list后端Spring Boot收到的URI是/api/user/list。这要求后端接口路径本身就包含/api前缀或者说后端能容忍这个前缀。带斜杠时Nginx会进行路径替换将location匹配到的那部分前缀替换为/。仍以上面为例location /api/ { proxy_pass http://127.0.0.1:8080/; }客户端请求/api/user/list后端收到的URI是/user/list。感觉像是把/api这个前缀“吃掉了”。类似的如果proxy_pass写成http://127.0.0.1:8080/v2/那么/api/user/list会被替换为/v2/user/list传给后端。我踩过最典型的一个坑是前端和后端联调前端请求/api/login后端接口实际是/login。前端项目里所有的请求都带/api前缀但Java接口类的RequestMapping里没写/api于是配置里漏了结尾的斜杠导致后端口口声声说找不到路由。这问题在联合调试时隐蔽性极强因为Nginx本身没有报错后端也没报错就是404。排查方法就是看后端access log里实际收到的URI一眼就能确认是不是路径被错误地保留了。3.4 转发请求头别让你的后端“失忆”反向代理隐藏了客户端的真实IP如果Nginx不把客户端的相关信息传递下去后端服务获取不到访客IP、无法判断请求来源是http还是https会出现“失忆”症状。所以配置里几乎必带下面这几行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;Host $host保持请求的原始域名这样后端的虚拟主机、权限校验、模板渲染都能拿到正确的Host。X-Real-IP是客户端真实IPX-Forwarded-For会追加每一层代理的IPX-Forwarded-Proto则告诉后端原始请求是http还是https。像Spring Boot内置的Tomcat、Nginx后端的日志分析工具很多都依赖这几个头部来展示真实访客IP。不配的话后端日志里看到的一律是127.0.0.1这会让你在排查安全和风控问题时无从下手。除了请求头还有几个proxy超时参数也需要关注。proxy_connect_timeout是Nginx与后端建立连接的等待时间默认60秒proxy_read_timeout是两次读取操作之间的间隔超时默认60秒。如果你的后端接口偶尔需要执行超过一分钟的长任务比如导出报表、批量审批默认超时会导致504。我一般会把proxy_read_timeout调到120秒甚至更长具体看业务。此外大文件上传要设置client_max_body_size默认1MB会直接憋死上传功能改为50m或更大是常见操作。4. 三个实战配置拿来就能抄4.1 前后端分离项目/api代理到后端服务现在主流的前后端分离开发模式前端用Vue、React后端用Spring Boot、Go、Node.js。部署的时候前端打包成静态文件放在Nginx上后端接口跑在某个本地端口。最直接的做法是把前端页面和服务端接口都放在同一个Nginx下通过location区分。先看完整配置server { listen 80; server_name www.example.com; # 前端静态资源 location / { root /opt/frontend/dist; index index.html; try_files $uri $uri/ /index.html; } # 后端接口代理 location /api/ { proxy_pass http://127.0.0.1:8080/api/; 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; client_max_body_size 50m; } # 静态资源单独走本地目录 location /static/ { alias /opt/frontend/dist/static/; expires 7d; } }这里几个关键点try_files $uri $uri/ /index.html;是给Vue/React的history路由模式用的。前端路由是/user/center这种地址但服务器上没有这个物理文件如果没有try_files兜底刷新页面就会出现404。有了这一行所有匹配不到文件的请求都会回到index.html前端路由接管后再渲染对应页面。/static/目录用alias指向本地目录而且加上expires 7d可以缓存静态资源减轻后端压力。后端接口的代理proxy_pass结尾带不带斜杠取决于后端接口是否包含/api前缀。如果后端Controller的RequestMapping里面没有加/api那proxy_pass http://127.0.0.1:8080/;可以帮你把前缀剥掉。这一点我在上一节已经详细讲过实际配置时先和后端确认清楚接口路由再决定写法。4.2 内网地图代理以百度地图为例有读者问过“内网要反向代理地图供内网使用应该怎么做以百度地图为例”这是个很典型的场景。企业内网为了安全通常不能直接访问外网但内部业务系统又需要展示地图。解决办法是让一台能够访问外网的服务器作为中转由Nginx代收地图请求再转发给百度地图服务器。这个需求的麻烦点在于地图服务并不是简单的一个API地址它包含页面、JavaScript脚本、CSS样式、瓦片数据等多个请求路径而且这些资源里硬编码了map.baidu.com这样的域名。代码层面如果直接请求我们自己的域名JS脚本里的域名不换浏览器还是会直接去请求外网地址照样被墙在门内。我在实际项目中采用过方案是Nginx代理百度的多个二级域名并用sub_filter模块替换响应内容里出现的域名。server { listen 80; server_name maps.internal.example.com; # 页面和API请求 location /baidu-map/ { proxy_pass https://map.baidu.com/; proxy_set_header Host map.baidu.com; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_ssl_server_name on; proxy_ssl_protocols TLSv1.2 TLSv1.3; proxy_redirect https://map.baidu.com/ /baidu-map/; sub_filter_once off; sub_filter //map.baidu.com //maps.internal.example.com/baidu-map; sub_filter_types text/html application/javascript text/css; } }sub_filter是Nginx的内容替换模块它会把后端返回的HTML、JS、CSS字符串里的//map.baidu.com替换成我们内网地址。sub_filter_once off表示替换所有匹配而不只是第一处。proxy_redirect把后端返回的Location响应头里的外网地址改写为内网地址。实际执行时还要注意几个细节。第一百度地图API会在Referer里做域名白名单校验你直接代理过去Referer是内网域名API可能会拒绝服务需要在百度地图开放平台把内网域名加进白名单。第二JS脚本里如果通过变量拼接地址而不是写死域名sub_filter就替换不了得配合更精细的改写规则或者直接在代码里配置地图服务的host指向。第三HTTPS证书问题内网域名需要配置SSL证书否则浏览器会拦截。这里我不建议把地图代理方案做成通用标准因为地图服务商的防盗链、跨域、证书策略各不相同更稳妥的做法是使用地图服务商提供的离线地图SDK或者自己做一个轻量TCP/HTTP转发中间层。但通过这个例子你可以掌握Nginx反向代理外网服务进内网的核心思路域名替换、响应体改写、Referer和Host处理。这套方法论在很多内网服务穿透场景里都通用。4.3 负载均衡配置让后端扛住高并发Nginx反向代理最经典的应用之一就是负载均衡。当单个后端服务扛不住并发压力把同样的服务部署到多台机器上Nginx作为流量入口把请求分发给各个后端实例。配置方式是在http块中定义一个upstream服务器组upstream backend_servers { # 默认按权重轮询 server 192.168.1.11:8080 weight3; server 192.168.1.12:8080 weight2; server 192.168.1.13:8080 weight1 max_fails3 fail_timeout30s; # keepalive 保持后端连接 keepalive 64; } server { listen 80; server_name www.example.com; location /api/ { proxy_pass http://backend_servers; 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_http_version 1.1; proxy_set_header Connection ; } }负载均衡的策略默认是轮询每个请求依次分发给后端后者挂了会自动摘除。weight参数调整分配比重性能好的机器权重给大一点。如果业务要求同一个用户的请求始终打到同一台后端比如Session存储在本地内存可以改用ip_hash策略upstream backend_servers { ip_hash; server 192.168.1.11:8080; server 192.168.1.12:8080; }ip_hash根据客户端IP计算哈希值相同IP的请求会被固定分配到同一台服务器。缺点是如果某个客户端的流量特别大可能造成单台机器过载。另外一个容易忽略的点是proxy_http_version 1.1;和proxy_set_header Connection ;其目的是启用Nginx到后端的HTTP长连接避免每个请求都重新建连。在高并发场景下这两行配置对后端性能的提升非常明显我实测过短连接和长连接模式下后端QPS可以有接近一倍的差距。高并发调优不仅靠负载均衡Nginx本身的参数也要配合。worker_processes auto;让CPU核心都用起来worker_connections 10240;提升单进程连接数上限keepalive_timeout 65;保持客户端连接gzip on;压缩传输数据减少带宽占用。把这些基础项调好一个普通的四核八G服务器扛住几千并发是没有问题的。5. 常见问题排查与避坑记录5.1 502和504最常见的两个“坏网关”502 Bad Gateway是Nginx反向代理配置里出现频率最高的报错。排查思路非常明确Nginx本身没事问题是Nginx转发请求之后后端没有给出正常响应。可能的原因有后端服务根本没启动、后端监听的IP端口写错、后端在处理请求时崩溃、防火墙或SELinux拦截了连接。我的排查顺序是先确认后端服务本身能不能直接访问在Nginx服务器上执行curl http://127.0.0.1:8080/health如果直接curl都失败问题在后端服务本身。如果curl正常但Nginx代理后502重点检查proxy_pass里的地址和端口是否错误、DNS解析是否正常、Nginx日志里有没有connect() failed (111: Connection refused)这种记录。还有一个容易被忽略的是SELinux。在RHEL系发行版上即使防火墙放行了端口SELinux也可能拦截Nginx发起对外连接。遇到这种情况执行curl时可能正常但通过Nginx访问就502。临时验证的方法是把SELinux设为许可模式setenforce 0如果问题消失那就是SELinux策略问题。永久解决方案是setsebool -P httpd_can_network_connect 1网上有不少人因为这一步卡了两三个小时。504 Gateway Time-out的含义是Nginx等待后端处理超时。后端接口执行时间过长超过了proxy_read_timeout或proxy_send_timeout的设定值。解决办法是调大超时时间例如proxy_read_timeout 300s;或者优化后端接口的响应速度。5.2 404与路径丢失location与proxy_pass的坑404问题在反向代理里经常不是后端路由写错而是URI在转发过程中变了形或根本没匹配到正确的location。典型场景一客户端请求/api/login配置里的location是/api不带尾部斜杠访问/api时正常但访问/api/login就是404。原因在于location /api匹配的是以/api开头的URI但proxy_pass http://backend;会把原始URI传过去后端如果预期路径是/api/login这不会404但如果后端预期是/login这里就出问题了需要按上文的斜杠规则调整。典型场景二是root和alias用混。在配置location时root和alias都能指定本地目录但逻辑不同。root /opt/html;会在访问/static/app.js时查找/opt/html/static/app.js而alias /opt/html/;会把location前缀替换为alias路径访问/static/app.js时查找/opt/html/app.js。如果你把alias写成root的样子资源路径会多出一层目录静态资源全部404。我建议静态资源目录统一用alias搭配location /static/前缀可读性更好也少犯错。要快速排查路径问题最直接的方法是看Nginx访问日志和后端应用日志里的实际URI对比前后端收到的地址差异一两分钟就能定位。5.3 重定向与WebSocket容易被忽略的细节有些后端服务在做用户认证之后会返回302重定向例如跳转到登录页。如果后端返回的Location是http://127.0.0.1:8080/login那么客户端会跟着Location直接访问这个内网地址结果当然是失败或者暴露了内网信息。Nginx提供了proxy_redirect来解决这个问题。默认值proxy_redirect default;会自动把后端返回的Location响应头里的http://127.0.0.1:8080替换为Nginx自己接收请求的地址。如果你后端返回的Location路径格式特殊可以用显式配置proxy_redirect http://127.0.0.1:8080/ /;WebSocket是现代Web应用很常用的协议做实时推送、聊天、在线协作都离不开。Nginx反向代理默认是按HTTP协议处理的WebSocket升级请求需要的Upgrade和Connection头不会自动保留必须显式配置location /ws/ { proxy_pass http://127.0.0.1:8080/ws/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_read_timeout 3600s; }proxy_read_timeout这里要特别注意WebSocket连接是长连接默认60秒没有数据就会断开。做在线聊天这类功能建议把超时时间设到数小时甚至不设超时否则用户会莫名其妙地频繁掉线。5.4 配置安全与性能小调优反向代理把后端服务隐藏得很好但Nginx自身也会暴露版本信息给攻击者可乘之机。隐藏版本号只需要一行server_tokens off;。如果你代理的是敏感内部系统再加上基于IP的访问控制没在名单里的IP直接拒绝location /admin/ { allow 192.168.1.0/24; deny all; proxy_pass http://127.0.0.1:8080/admin/; }日志方面access_log off;可以关闭静态资源目录的访问日志因为大量图片、JS、CSS的日志除了撑爆磁盘没有太多分析价值。动态接口的日志则建议保留并开启log_format后面排查问题时非常有用。最后分享一个压箱底的习惯每次要改动Nginx配置之前先备份当前配置文件比如cp nginx.conf nginx.conf.bak.20250101。不要问我为什么我只知道有一次我改完配置reload之后忘了具体改了哪些行找了两小时才靠备份对比找回旧配置。配置文件应该纳入版本管理Git仓库里留一份服务器上再留一份线上出问题恢复起来会快得多。在我实际配置Nginx的经验里最难的不是记住指令而是理解每个指令背后的数据流。客户端请求到了Nginx之后怎么匹配location、URI如何拼接、请求头怎么变换、后端返回之后又做了什么改写——脑子里有一条清晰的链路配置起来就很少出错。遇到问题也别慌先看/var/log/nginx/error.log再确认location匹配顺序最后检查后端地址和超时设置八成的问题都能在这三步里解决。希望这篇文章能让你在配置Nginx反向代理时少走点弯路。