Nginx反向代理怎么配置?从零到实战的完整指南

来源:C++教程作者:台湾程序员头衔:程序员
导读:本期聚焦于台湾程序员创作的《Nginx反向代理怎么配置?从零到实战的完整指南》,敬请观看详情。Nginx反向代理在配置层面看似只有proxy_pass一条指令,实际背后是ngx_http_proxy_module对两段HTTP连接的完整管理:客户端连接负责请求接收,上游连接负责内容回源,中间还要处理请求头重写、URI路径迁移、响应缓冲和超时控制。理解这个模型后,再去配置多个后端服务的路径分发、WebSocket长连接升级和上游容错,就不容易受到默认行为干扰。本文会先拆开正向代理与反向代理的边界,然后用一组最小可用配置完成第一个反向代理,接着展开多个location的实战写法,重点说明proxy_pass末尾斜杠如何改变URI传递结果。WebSocket场景会解释Upgrade与Connection头的必要配置,最后补充缓存、缓冲、超时和fail_timeout等生产级参数。读者可以按照从零到实战的路径搭建自己的Nginx代理层,避免只复制配置却不知道每行含义。

Nginx反向代理在实际项目中扮演的角色,是把分散在不同端口、不同主机上的后端服务收拢到同一个入口。客户端请求到达Nginx后,Nginx再以代理身份向后端服务发起新请求,把响应取回来交还给客户端。这样可以隐藏后端真实地址、统一日志格式、集中处理TLS证书,也方便做灰度发布和故障切换。

Nginx反向代理怎么配置?从零到实战的完整指南

从Nginx内部看,反向代理不是简单的数据转发。它涉及两个独立连接:客户端到Nginx的连接,以及Nginx到上游服务的连接。每个连接的建立时间、读取超时、响应缓冲、请求头重写,都会影响最终体验。只有把这些环节拆开理解,配置时才知道每一行在解决什么问题。

一、先分清正向代理与反向代理

正向代理和反向代理经常被放在一起比较,但二者面向的对象完全不同。正向代理站在客户端一侧,代理的是浏览器或终端程序。当你配置了正向代理后,客户端访问外部网站时,请求先发给代理服务器,由代理服务器去目标站点取数据。正向代理可以帮助内网用户访问外部网络,也可以隐藏客户端的真实出口IP。

反向代理则站在服务端一侧,代理的是后端应用。客户端通常并不知道代理的存在,以为自己直接访问的是业务系统。实际上请求先到Nginx,再由Nginx转发给后端的Tomcat、Node.js、Python服务或其他进程。客户端只能看到Nginx暴露的地址,后端的端口、内部域名、服务器数量都可以对外隐藏。

在Nginx中实现反向代理,核心指向是proxy_pass指令。它隶属于ngx_http_proxy_module模块,这个模块默认已经编译进Nginx。也就是说,只要安装了标准版本的Nginx,不需要额外扩展,就可以直接使用HTTP反向代理能力。更高层的负载均衡、缓存、重试机制,都是围绕这个模块展开的。

二、最小可用的反向代理配置

从零开始配置一个反向代理,只需要一个server块和一个location块。假设本机8080端口已经运行了一个后端服务,想让访问80端口的用户自动获取8080端口的内容,可以使用下面这段配置。

server {
    listen 80;
    server_name app.ipipp.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;
    }
}

这段配置中,listen 80表示Nginx监听80端口,server_name用来匹配请求头中的Host域名。当请求进入location /后,proxy_pass会把请求转发到http://127.0.0.1:8080。后面三行proxy_set_header负责把原始请求头补充完整,让后端服务知道客户端真实IP和原始域名,否则后端拿到的会是Nginx自己的IP。

配置完成后,可以先用nginx -t检查语法,再执行nginx -s reload让配置生效。如果是在容器环境中,也可以使用nginx -s reload或直接重启容器。验证时打开浏览器访问http://app.ipipp.com,如果后端服务正常,就能看到预期内容。

这里有一个非常容易踩坑的细节:proxy_pass末尾是否带斜杠。假设请求URI是/api/user/list,如果写成proxy_pass http://127.0.0.1:8080/;,Nginx会把location匹配到的部分替换为一个斜杠再拼接剩余内容,实际转发上游的路径会变成/user/list。如果写成proxy_pass http://127.0.0.1:8080;,则原始URI会整体保留,上游收到的仍然是/api/user/list。这个差异在前后端分离项目中尤其重要,经常导致404或接口路径不一致。

三、多后端路径分发实战

真实业务不会只有一个后端,常见结构是前端静态页面、API接口、管理后台分别运行在不同端口。Nginx可以通过多个location把不同前缀的路径分发到不同上游。这样外部只需要暴露一个域名,就能访问多个内部服务。

server {
    listen 80;
    server_name app.ipipp.com;

    location / {
        proxy_pass http://127.0.0.1:5000;
    }

    location /api/ {
        proxy_pass http://127.0.0.1:8080/;
    }

    location /admin/ {
        proxy_pass http://127.0.0.1:9090/;
    }
}

这段配置中,访问根路径/会转发到5000端口的前端服务;访问/api/会转发到8080端口的接口服务;访问/admin/会转发到9090端口的管理后台。注意/api/和/admin/后面的proxy_pass末尾都带了斜杠,这样实际转发时/api/和/admin/前缀会被去掉,后端接收到的路径更干净。如果这里又写成不带斜杠,后端就会收到带前缀的完整路径,需要在应用层再处理一次。

Nginx的location匹配不是从上到下找到哪个算哪个。它有一套优先级规则:精确匹配优先级最高,其次是带正则的location ~或location ~*,再然后是普通前缀匹配,其中最长前缀优先。配置多个location时,不要随意调换顺序,否则可能被正则规则提前拦截。对于路径分发场景,推荐尽量使用普通前缀匹配,只有确实需要模糊匹配时才使用正则。

如果同一个后端服务部署了多个实例,可以使用upstream块定义服务器组,让Nginx在多个实例之间做轮询。比如后端8080和8081都运行着相同服务,可以这样配置。

upstream backend_api {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}

server {
    listen 80;
    server_name app.ipipp.com;

    location /api/ {
        proxy_pass http://backend_api/;
    }
}

这里的proxy_pass指向的是upstream定义的组名backend_api。Nginx会按请求顺序轮流把流量分配给8080和8081。默认策略是加权轮询,如果实例性能不同,可以给server加上weight参数,例如server 127.0.0.1:8080 weight=3;表示这个实例承载更多请求。生产环境中通常会结合健康检查参数,避免把请求发给已经挂掉的实例。

四、WebSocket与长连接场景

普通HTTP请求一次请求一次响应,连接复用程度有限。但WebSocket建立后,客户端和服务器之间会保持一条长连接,双向持续传输数据。要让Nginx正确反向代理WebSocket,不能只写proxy_pass,还必须处理升级请求。WebSocket握手时,客户端会发送Upgrade: websocket和Connection: Upgrade两个头,Nginx默认不会自动把这两个头转发给上游。

location /ws/ {
    proxy_pass http://127.0.0.1:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 3600s;
}

这里先把代理协议版本提升到1.1,因为HTTP/1.1才支持协议升级。proxy_set_header Upgrade $http_upgrade会把客户端带来的Upgrade头原样转发。Connection "upgrade"表示告诉上游连接需要升级。最后把proxy_read_timeout调大,避免长连接空闲一段时间后被Nginx主动断开。默认读取超时是60秒,对WebSocket来说太短了,聊天室、在线协作、实时监控等场景都需要大幅调高。

更稳妥的做法是使用map指令动态设置Connection头。因为某些客户端可能不会发送Upgrade头,如果无脑写死Connection: upgrade,普通HTTP请求会出现异常。可以使用下面这段配置。

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    listen 80;

    location /ws/ {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_read_timeout 3600s;
    }
}

这样当$http_upgrade为空时,Connection会被设置为close,普通请求可以正常结束。当客户端确实携带Upgrade时,连接才会保持升级状态。WebSocket代理调试时,建议优先确认上游服务是否已监听正确端口,再查看Nginx的错误日志中是否有upgrade相关提示,最后再检查浏览器的Network面板是否完成了101 Switching Protocols。

五、缓存、缓冲与故障转移

反向代理不只是转发流量,还可以通过缓冲和缓存减轻上游压力。Nginx默认开启proxy_buffering,当上游响应速度很快、客户端读取速度很慢时,Nginx会先把响应内容写入缓冲区,再逐步发送给客户端。这样上游服务可以快速完成请求处理,不需要被慢客户端长时间占用连接。缓冲区大小可以通过proxy_buffer_size和proxy_buffers调整,但通常情况下默认值已经够用。

对于大文件下载或流式响应,关闭缓冲反而更合适。比如服务器返回的是实时日志、SSE事件流或大文件分块,如果Nginx先把整块响应缓存起来,用户可能迟迟看不到数据。此时可以设置proxy_buffering off;,让Nginx收到多少就转发多少,降低首字节延迟。另外还可以通过proxy_cache_path和proxy_cache配置HTTP缓存,把可复用的响应直接缓存在Nginx侧,减少对上游的重复请求。

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:10m max_size=1g inactive=60m use_temp_path=off;

server {
    listen 80;

    location /static/ {
        proxy_pass http://backend_static;
        proxy_cache api_cache;
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 404 1m;
        add_header X-Cache-Status $upstream_cache_status;
    }
}

这里的proxy_cache_path定义了缓存目录、缓存层级、内存区域和最大占用空间。proxy_cache_valid针对不同状态码设置缓存时间,200和302响应缓存10分钟,404响应只缓存1分钟。add_header把缓存命中状态暴露给客户端,方便调试时观察是否命中。缓存的清理需要借助proxy_cache_purge或商业版模块,开源版没有直接删除单条缓存的能力,这一点在规划时要提前考虑。

故障转移方面,可以配合upstream中的max_fails和fail_timeout实现简单健康检查。默认情况下,某个上游实例请求失败后,Nginx会继续尝试,直到达到max_fails阈值,才会在fail_timeout时间内暂时把它摘除。示例配置如下。

upstream backend_api {
    server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8081 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8082 backup;
}

这段配置表示8080和8081分别允许连续失败3次,超过后30秒内不再分配请求。8082被标记为backup,只有在所有普通实例都不可用时才会启用。临时故障转移还可以配合proxy_next_upstream控制哪些错误会触发重试,例如连接失败、超时或上游返回502时,自动把请求转给下一个实例。重试会带来额外延迟,写多读少的接口可以适当重试,对延迟敏感的接口则应谨慎开启。

反向代理配置最终要回到业务场景本身。路径规则、超时时间、缓冲策略、故障转移机制,都需要和实际后端行为匹配。先把最小配置跑通,再根据日志和监控逐项调整,是避免反向代理配置失控的最稳妥方式。

Nginx反向代理反向代理配置负载均衡修改时间:2026-10-02 09:06:11

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/1002/64598.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。