一文搞懂 Nginx 反向代理:从基础配置到生产实践

📅 2026/8/11 3:03:40
一文搞懂 Nginx 反向代理:从基础配置到生产实践
反向代理反向代理介绍正向代理替客户端办事隐藏客户端反向代理替服务器办事隐藏服务器反向代理reverse proxy指的是代理外网用户的请求到内部的指定的服务器并将数据返回给用户。客户端不直接与后端服务器进行通信而是与反向代理服务器进行通信,隐藏了后端服务器的 IP 地址。反向代理的主要作用是提供负载均衡和高可用性负载均衡Nginx可以将传入的请求分发给多个后端服务器以平衡服务器的负载提高系统性能和可靠性。缓存功能Nginx可以缓存静态文件或动态页面减轻服务器的负载提高响应速度。动静分离将动态生成的内容如 PHP、Python、Node.js 等和静态资源如 HTML、CSS、JavaScript、图片、视频等分别存放在不同的服务器或路径上。多站点代理Nginx可以代理多个域名或虚拟主机将不同的请求转发到不同的后端服务器上实现多个站点的共享端口。Location 配置Location 配置语法Nginx 使用 location 匹配规则 proxy_pass 反向代理指令实现反向代理功能匹配本质是 “URL 路径匹配 → 命中对应规则 → 转发至指定后端地址”。location 定义匹配路径proxy_pass 指定后端服务地址http { # 后端服务可配置 upstream 集群推荐支持负载均衡 upstream backend_nginx { nginx 192.168.1.100:8080; # 后端服务1 nginx 192.168.1.101:8080; # 后端服务2多节点自动轮询负载均衡 } server { listen 80; # Nginx 监听端口 server_name localhost; # 访问域名/IP # 1. 匹配所有请求兜底规则 location / { proxy_pass http://backend_nginx; # 转发至 upstream 集群 # 必加的反向代理核心参数传递客户端真实信息、适配后端服务 proxy_set_header Host $host; # 传递客户端访问的域名 proxy_set_header X‑Real‑IP $remote_addr; # 传递客户端真实IP proxy_set_header X‑Forwarded‑For $proxy_add_x_forwarded_for; #传递IP链 proxy_set_header X‑Forwarded‑Proto $scheme; # 传递请求协议http/https } # 2. 匹配特定路径如 /api 开头的请求单独转发 location /api/ { proxy_pass http://192.168.1.102:9090/; # 后端地址末尾带 /会剔除匹配的/api/ proxy_set_header Host $host; proxy_set_header X‑Real‑IP $remote_addr; } } }Location 匹配规则后端匹配逻辑URL 路径 → 按 location 优先级命中规则 → 由规则内的 proxy_pass 转发至对应后端优先级精确匹配 () 前缀匹配 (^~) 正则匹配 (/*) 普通前缀 兜底 (/);URL 重构关键:proxy_pass 末尾是否带 /, 决定是否剔除 location 匹配的路径前缀。精确匹配 ()语法:location /path {…}逻辑仅当请求 URL 与 /path 完全一致时命中优先级最高。示例:# 仅匹配 http://localhost/login,不匹配 /login?a1、/login/ location /login { proxy_pass http://backend_login:8080; }前缀匹配 (^~)语法:location ^~ /path {…}逻辑URL 以 /path 开头即命中优先级仅次于精确匹配会跳过正则匹配。用途优先匹配静态资源 (如 /static、/img) 或特定业务路径避免被正则规则拦截。示例:# 匹配所有 /static 开头的请求(如 /static/css/main.css、/static/img/1.jpg) location ^~ /static/ { proxy_pass http://backend_static:80; }正则匹配 (~ / ~*)语法:区分大小写:location ~ /regex {…} (如 /API 不匹配 /api 规则)不区分大小写:location ~* /regex { … } (如 /API、/api 均匹配)逻辑URL 符合正则表达式即命中优先级低于前缀匹配 (^~), 多个正则规则按定义顺序匹配先命中先生效。示例:# 匹配所有 .jpg、.png、.gif 结尾的图片请求(不区分大小写) location ~* \.(jpg|png|gif)$ { proxy_pass http://backend_img:80; }普通前缀匹配 (无符号)语法:location /path {…}逻辑URL 以 /path 开头即命中优先级低于正则匹配多个普通前缀规则按 “路径最长” 优先命中。示例:# 规则1:匹配 /api/xxx(路径长度3) location /api/ { proxy_pass http://backend_api:9090; } # 规则2:匹配 /api/user/xxx(路径长度7,比规则1长,优先命中) location /api/user/ { proxy_pass http://backend_user:9090; }通用匹配 (/)语法:location / {…}逻辑所有未被上述规则命中的请求都会匹配此规则 (兜底), 优先级最低。用途通常作为全局反向代理转发所有默认请求到主后端服务。proxy_pass 后端地址细节proxy_pass 末尾是否带 / , 会直接改变转发到后端的 URL 路径这是后端匹配后 “URL 重构” 的核心分 2 种场景:场景 1:proxy_pass 末尾带 /逻辑转发时会剔除 location 匹配的路径前缀将剩余路径拼接在后端地址后。示例:# location 匹配 /api/,proxy_pass 末尾带 / location /api/ { proxy_pass http://192.168.1.102:9090/; } # 实际转发逻辑: # 客户端请求 http://localhost/api/user/list → 后端接收 http://192.168.1.102:9090/user/list场景 2:proxy_pass 末尾不带 /逻辑转发时会保留 location 匹配的路径前缀直接拼接在后端地址后。示例:# location 匹配 /api/,proxy_pass 末尾不带 / location /api/ { proxy_pass http://192.168.1.102:9090; } # 实际转发逻辑: # 客户端请求 http://localhost/api/user/list → 后端接收 http://192.168.1.102:9090/api/user/list综合示例http { upstream backend_main { nginx 192.168.1.200:8080; } upstream backend_api { nginx 192.168.1.201:9090; } upstream backend_static { nginx 192.168.1.202:80; } upstream backend_login { nginx 192.168.1.203:8080; } server { listen 80; server_name localhost; # 1. 精确匹配: 仅 /login → 后端 login 服务 location /login { proxy_pass http://backend_login; proxy_set_header Host $host; } # 2. 前缀匹配: /static/ 开头 → 后端静态服务(跳过正则) location ^~ /static/ { proxy_pass http://backend_static/; proxy_set_header Host $host; } # 3. 正则匹配: 图片后缀 → 后端静态服务 location ~* \.(jpg|png|gif)$ { proxy_pass http://backend_static; proxy_set_header Host $host; } # 4. 普通前缀: /api/ 开头 → 后端 api 服务 location /api/ { proxy_pass http://backend_api/; proxy_set_header Host $host; proxy_set_header X‑Real‑IP $remote_addr; } # 5. 兜底匹配: 所有未命中的请求 → 主后端服务 location / { proxy_pass http://backend_main; proxy_set_header Host $host; proxy_set_header X‑Real‑IP $remote_addr; } } }反向代理实践环境/etc/hosts 配置所有节点统一配置[rootnginx ~]# vim /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 ############ proxy ################## 10.1.8.11 client.laogao.cloud client 10.1.8.20 www.laogao.cloud www 10.1.8.20 proxy.laogao.cloud proxy 10.1.8.21 nginx1.laogao.cloud nginx1 10.1.8.22 nginx2.laogao.cloud nginx2 10.1.8.23 nginx3.laogao.cloud nginx3后端 nginx 服务器配置除了客户端所有节点安装 nginx 并启动 nginx 服务。 [rootproxy,nginx1,nginx2,nginx3 ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo [rootproxy,nginx1,nginx2,nginx3 ~]# yum -y install nginx # 启动并启用服务 [rootproxy,nginx1,nginx2,nginx3 ~]# systemctl enable nginx --now # 防火墙设置 [rootproxy,nginx1,nginx2,nginx3 ~]# firewall-cmd --add-servicehttp --permanent [rootproxy,nginx1,nginx2,nginx3 ~]# firewall-cmd --reload 准备主页 - 后端节点 [rootnginx1 ~]# echo Welcome to $(hostname) /usr/share/nginx/html/index.html [rootnginx2 ~]# echo Welcome to $(hostname) /usr/share/nginx/html/index.html [rootnginx3 ~]# echo Welcome to $(hostname) /usr/share/nginx/html/index.html 客户端测试后端服务 [rootnginx-client ~]# curl http://nginx1.laogao.cloud/ Welcome to nginx1.laogao.cloud [rootnginx-client ~]# curl http://nginx2.laogao.cloud/ Welcome to nginx2.laogao.cloud [rootnginx-client ~]# curl http://nginx3.laogao.cloud/ Welcome to nginx3.laogao.cloud前端 proxy 服务器配置准备主页 - 代理节点 [rootproxy ~]# echo Welcome to www.laogao.cloud /usr/share/nginx/html/index.html [rootproxy ~]# mkdir /var/nginx [rootproxy ~]# echo Hello, Nginx /var/nginx/index.html [rootproxy ~]# echo Hello, laogao /var/nginx/test.txt [rootproxy ~]# cp /usr/share/nginx/html/nginx-logo.png /var/nginx/ [rootproxy ~]# ls /var/nginx/ index.html nginx-logo.png test.txt 代理节点基础静态配置 [rootproxy ~]# vim /etc/nginx/conf.d/proxy.conf server { listen 80; server_name www.laogao.cloud; # 匹配根位置 location / { root /var/nginx; index index.html; } } 重新加载nginx配置 [rootproxy ~]# nginx -s reload 客户端静态资源测试 [rootnginx-client ~]# curl http://www.laogao.cloud/ Hello, Nginx [rootnginx-client ~]# curl http://www.laogao.cloud/test.txt Hello, laogao反向代理基础实践-代理本地环境准备 [rootproxy ~]# mkdir /var/nginx/nginx{1,2} [rootproxy ~]# echo Hello, Im here /var/nginx/nginx1 /var/nginx/nginx1/index.html [rootproxy ~]# echo Hello, Im here /var/nginx/nginx2 /var/nginx/nginx2/index.html [rootproxy ~]# mkdir /var/nginx{1,2} [rootproxy ~]# echo Hello, Nginx1 /var/nginx1/index.html [rootproxy ~]# echo Hello, Nginx2 /var/nginx2/index.html # 目录结构查看 [rootproxy ~]# tree /var/nginx* /var/nginx ├── index.html ├── nginx1 │ └── index.html ├── nginx2 │ └── index.html ├── nginx-logo.png └── test.txt /var/nginx1 └── index.html /var/nginx2 └── index.html 2 directories, 7 files # 创建www测试目录 [rootproxy ~]# \ for path1 in www{1..2} do for path2 in nginx{1..2} do mkdir -p /var/$path1/$path2 echo Hello, Im here /var/$path1/$path2 /var/$path1/$path2/index.html done done [rootproxy ~]# tree /var/www* /var/www1 ├── nginx1 │ └── index.html └── nginx2 └── index.html /var/www2 ├── nginx1 │ └── index.html └── nginx2 └── index.html 4 directories, 4 files基本测试[rootnginx-client ~]# curl http://www.laogao.cloud/ Hello, Nginx # 访问/nginx1/ [rootnginx-client ~]# curl http://www.laogao.cloud/nginx1/ Hello, Im here /var/nginx/nginx1 # 访问/nginx2/ [rootnginx-client ~]# curl http://www.laogao.cloud/nginx2/ Hello, Im here /var/nginx/nginx2实践1无符号匹配[rootproxy ~]# vim /etc/nginx/conf.d/proxy.conf server { listen 80; server_name www.laogao.cloud; # 匹配根位置 location / { root /var/nginx; index index.html; } # 匹配/nginx1时/var目录下找nginx1完整路径是/var/nginx1 location /nginx1 { root /var; # 等效于下面的 alias 语句必须使用绝对路径 # alias /var/nginx1; index index.html; } } # 重新加载nginx配置 [rootproxy ~]# nginx -s reload 测试 # nginx1 后面必须添加 / 符号 [rootnginx-client ~]# curl http://www.laogao.cloud/nginx1/ Hello, Nginx1 # 显示结果是目录/var/nginx1中内容 # nginx2 后面必须添加 / 符号 [rootnginx-client ~]# curl http://www.laogao.cloud/nginx2/ Hello, Im here /var/nginx/nginx2 # 显示结果是目录/var/nginx/nginx2中内容 实验结果无符号匹配优先级高于默认的/。实践2正则表达式匹配[rootproxy ~]# vim /etc/nginx/conf.d/proxy.conf server { listen 80; server_name www.laogao.cloud; # 匹配根位置 location / { root /var/nginx; index index.html; } # 匹配/nginx1时/var目录下找nginx1完整路径是/var/nginx1 location /nginx1 { root /var; # 等效于下面的 alias 语句必须使用绝对路径 # alias /var/nginx1; index index.html; } # 正则表达式匹配 /nginx.* location ~ /nginx.* { root /var/www1; index index.html; } } # 重新加载nginx配置 [rootproxy ~]# nginx -s reload 测试 # nginx1 后面必须添加 / 符号 [rootnginx-client ~]# curl http://www.laogao.cloud/nginx1/ Hello, Im here /var/www1/nginx1 # 显示结果是目录/var/www1/nginx1中内容 # nginx2 后面必须添加 / 符号 [rootnginx-client ~]# curl http://www.laogao.cloud/nginx2/ Hello, Im here /var/www1/nginx2 # 显示结果是目录/var/www1/nginx2中内容 实验结果正则表达式匹配优先级高于无符号。实践3精确匹配[rootproxy ~]# vim /etc/nginx/conf.d/proxy.conf server { listen 80; server_name www.laogao.cloud; # 匹配根位置 location / { root /var/nginx; index index.html; } # 匹配/nginx1时/var目录下找nginx1完整路径是/var/nginx1 location /nginx1 { root /var; # 等效于下面的 alias 语句必须使用绝对路径 # alias /var/nginx1; index index.html; } # 正则表达式匹配 /nginx.* location ~ /nginx.* { root /var/www1; index index.html; } # 精确匹配 location /nginx2/index.html { root /var/www2; index index.html; } } # 重新加载nginx配置 [rootproxy ~]# nginx -s reload 测试 # nginx1 后面必须添加 / 符号 [rootnginx-client ~]# curl http://www.laogao.cloud/nginx1/ Hello, Im here /var/www1/nginx1 # 显示结果是目录/var/www1/nginx1中内容 # nginx2 后面必须添加 / 符号 [rootnginx-client ~]# curl http://www.laogao.cloud/nginx2/ Hello, Im here /var/www2/nginx2 # 显示结果是目录/var/www2/nginx2中内容 实验结果精确匹配优先级高于正则表达式。