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 反向代理正在正常工作!

相关推荐
Ahu_iii2 小时前
【Linux】基础知识与操作汇总:一份给新手的 Linux 学习总结
linux·运维·学习
ZLRRLZ2 小时前
【Linux操作系统】基础开发工具
linux·运维·服务器
羚羊角uou3 小时前
【Linux】线程控制
linux·运维·服务器
ftswsfb3 小时前
Docker进阶-管理和应用
运维·docker·容器
1白天的黑夜14 小时前
Linux(4)|入门的开始:Linux基本指令(4)
linux·运维·服务器·centos
wanhengidc4 小时前
云手机:云计算的灵动化身
运维·服务器·人工智能·游戏·智能手机·云计算
励志不掉头发的内向程序员4 小时前
【Linux系列】让 Vim “跑”起来:实现一个会动的进度条
linux·运维·服务器·开发语言·学习
IT古董5 小时前
L4 vs L7 负载均衡:彻底理解、对比与实战指南
运维·负载均衡
Gss7775 小时前
HAProxy 技术解析与负载均衡体系梳理
运维·负载均衡