Nginx反向代理核心原理揭秘

它触及了 Nginx 作为反向代理服务器的核心工作原理。观察到的现象正是 Nginx 设计的精妙之处。

核心原理:Nginx 是"中间人"

后端并没有直接"传给前端"数据,而是传给 Nginx,再由 Nginx 转发给前端

整个数据流是这样的:

复制代码
前端浏览器 ←→ Nginx(90端口) ←→ 后端应用(8080端口)

详细的工作流程

1. 请求阶段(前端 → Nginx → 后端)

前端浏览器 请求: http://域名:90/api Nginx:90端口 转发请求到 http://localhost:8080/api 后端Spring应用:8080端口

2. 响应阶段(后端 → Nginx → 前端)

后端Spring应用:8080端口 返回数据给 Nginx Nginx 将数据返回给前端浏览器

为什么后端不需要知道前端的存在?

关键机制:反向代理配置

Nginx 的配置中定义了代理规则,告诉 Nginx:"当收到对90端口的请求时,实际去8080端口获取数据"。

nginx 复制代码
# Nginx 配置文件示例 (nginx.conf)
server {
    listen 90;  # Nginx 监听90端口
    
    server_name localhost;
    
    # 静态文件服务
    location / {
        root /usr/share/nginx/html;  # 前端文件目录
        index index.html index.htm;
    }
    
    # API 代理配置 - 这是关键!
    location /api/ {
        proxy_pass http://localhost:8080/;  # 将/api请求转发到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;
    }
}

后端视角:谁在调用我?

从后端应用的角度看,它并不知道前端浏览器的存在。它只知道:

  1. 有一个客户端(Nginx)向我的8080端口发起了请求
  2. 我处理这个请求并返回响应给这个客户端(Nginx)
  3. 至于这个客户端(Nginx)之后要做什么,我完全不关心
java 复制代码
// 后端Spring应用(运行在8080端口)
@RestController
public class UserController {
    
    @GetMapping("/api/users")
    public List<User> getUsers() {
        // 这个方法只知道:有人调用了 /api/users
        // 它返回数据给调用者(Nginx),不知道最终是浏览器
        return userService.findAll();
    }
}

这种架构的优势

1. 解耦前后端

  • 前端只需要与 Nginx(90端口) 通信
  • 后端只需要处理来自 Nginx 的请求
  • 双方技术栈可以独立演进

2. 负载均衡

nginx 复制代码
# Nginx 可以将请求分发到多个后端实例
upstream backend_servers {
    server localhost:8080 weight=3;  # 权重3
    server localhost:8081 weight=2;  # 权重2
    server localhost:8082 weight=1;  # 权重1
}

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

3. 安全性

  • 后端服务(8080)可以不暴露给外网,只允许 Nginx 访问
  • Nginx 可以作为安全屏障,过滤恶意请求

4. 性能优化

nginx 复制代码
# Nginx 可以处理静态资源,减轻后端压力
location /static/ {
    root /usr/share/nginx/html;
    expires 30d;  # 缓存30天
}

location /api/ {
    proxy_pass http://localhost:8080/;
    # 添加缓存
    proxy_cache my_cache;
    proxy_cache_valid 200 302 10m;
}

实际的数据流示例

让我们跟踪一个具体的请求:

步骤1:浏览器发起请求

复制代码
前端浏览器 → http://example.com:90/api/users

步骤2:Nginx 接收并转发

nginx 复制代码
# Nginx 配置匹配到 location /api/
location /api/ {
    proxy_pass http://localhost:8080/;  # 转发到8080端口
}

实际转发为:http://localhost:8080/api/users

步骤3:后端处理并响应

java 复制代码
// Spring 后端收到请求,返回JSON数据
@GetMapping("/api/users")
public List<User> getUsers() {
    return Arrays.asList(
        new User(1, "Alice"),
        new User(2, "Bob")
    );
}
// 响应:HTTP 200 + JSON数据

步骤4:Nginx 返回给浏览器

复制代码
Nginx 收到后端响应,原样返回给浏览器
浏览器显示结果,但地址栏显示的是90端口

解决常见的跨域问题

这种架构还天然解决了前后端分离中的跨域问题

没有 Nginx 时的跨域问题:

复制代码
前端: http://localhost:3000 (React开发服务器)
后端: http://localhost:8080 (SpringBoot)

浏览器阻止请求:不同端口被视为不同源,违反同源策略

使用 Nginx 反向代理解决:

复制代码
浏览器访问: http://localhost:90
Nginx 服务静态文件(前端) + 代理API请求到8080端口

对浏览器来说,所有资源都来自同一个源(localhost:90),没有跨域问题

总结

Nginx 能够成功中转数据的核心原因是:

  1. 反向代理机制:Nginx 作为中间人,接收前端请求并转发给后端
  2. 配置规则 :通过 proxy_pass 指令定义转发规则
  3. 网络可达性:Nginx 和后端应用在同一台机器或同一网络内,可以互相访问
  4. 透明传输:Nginx 只是中转数据,不修改业务逻辑(除非特别配置)

这种架构是现代 Web 应用的标准做法,它提供了更好的安全性、可扩展性和维护性。正好验证了 Nginx 反向代理正在正常工作!

相关推荐
starzy19905 小时前
虚拟化解决方案全景:软件虚拟化、硬件虚拟化与 Docker 的位置
运维·docker·容器
Neighbor_OldY6 小时前
云上安全配置审计与误配置修复实战:从安全组、OSS、RAM到数据库的全栈排查复盘
大数据·运维·安全·云计算
开心大爆炸7 小时前
xrdp 连接 登录对话框输入密码后闪退
linux·运维·服务器
苏生Susheng8 小时前
【软件实施】Linux系统Shell脚本教程
linux·运维·服务器·chrome·spring boot·学习·实施
2601_962304918 小时前
把出片接进自动化流水线:2026 年批量 AI 视频生成工具的脚本契约与同类项目对照
运维·人工智能·自动化
Ruiery9 小时前
Linux 6.6内核 IOMMU 深度解析(七):DMA API 与 IOMMU 集成 — 从 dma_map_single 到 iommu_map
linux·运维·服务器
snow@li9 小时前
服务器运维:Alibaba Cloud Linux 4 LTS 64位 根目录全景深度解析文章
linux·运维·服务器
实战派K8S&DB9 小时前
《基于 Dify + FastAPI + PyTiDB 搭建大模型驱动的 TiDB 智能运维 Agent》
运维·数据库·分布式·云原生·tidb·fastapi
苏生Susheng9 小时前
【软件实施】Linux企业运维常用命令手册
java·linux·运维·服务器·springboot·springcloud·软件实施
名字还没想好☜10 小时前
Docker buildx 多架构镜像实战:一次构建 amd64+arm64,告别 exec format error
运维·docker·eureka·架构·kubernetes