前后端交互原理与架构全解

复制代码
一、总体架构概览

现代 Web 应用采用三层架构(Three-Tier Architecture):

复制代码
用户(浏览器) ⟷ 前端(Client) ⟷ 后端(Server) ⟷ 数据库(Database)

二、前端部分

2.1 前端是什么

前端是用户直接看到和操作的部分,运行在用户的浏览器中。

核心三件套:

技术 职责
HTML 结构(骨架)
CSS 样式(皮肤)
JavaScript 行为(交互逻辑)

现代前端通常使用框架:React、Vue、Angular 等,它们最终都会被编译成 HTML + CSS + JS。

2.2 前端资源的加载过程

当用户在浏览器输入 URL 并回车:

  1. DNS 解析 :将域名(如 www.example.com)解析为 IP 地址(如 93.184.216.34

  2. TCP 三次握手:浏览器与服务器建立 TCP 连接

  3. TLS 握手(若 HTTPS):建立加密通道

  4. 发送 HTTP 请求GET / HTTP/1.1

  5. 服务器返回 HTML:浏览器开始解析

  6. 解析 HTML 时发现 CSS/JS/图片等资源:再次发起 HTTP 请求获取

  7. 渲染页面:构建 DOM 树 → CSSOM 树 → 合成渲染树 → 布局 → 绘制


三、前后端交互

3.1 核心协议:HTTP/HTTPS

HTTP (HyperText Transfer Protocol)是前后端通信的基础协议,基于请求-响应模型。

HTTP 请求的结构
复制代码
POST /api/users HTTP/1.1          ← 请求行(方法 + 路径 + 协议版本)
Host: www.example.com              ← 请求头(Headers)
Content-Type: application/json
Authorization: Bearer eyJhbGc...
​
{                                  ← 请求体(Body)
  "name": "张三",
  "age": 25
}
HTTP 响应的结构
复制代码
HTTP/1.1 200 OK                    ← 状态行(协议版本 + 状态码 + 原因短语)
Content-Type: application/json     ← 响应头
Set-Cookie: session=abc123
​
{                                  ← 响应体
  "id": 1,
  "name": "张三",
  "age": 25
}
常见 HTTP 方法
方法 语义 典型用途
GET 获取资源 查询数据
POST 创建资源 提交表单、新增数据
PUT 全量更新资源 修改整条记录
PATCH 部分更新资源 修改某个字段
DELETE 删除资源 删除数据
常见状态码
状态码 含义
200 成功
201 创建成功
301/302 重定向
400 客户端请求错误
401 未认证
403 无权限
404 资源不存在
500 服务器内部错误
HTTPS = HTTP + TLS/SSL

HTTPS 在 HTTP 之下加了一层 TLS(Transport Layer Security) 加密层:

复制代码
应用层:   HTTP
安全层:   TLS/SSL        ← HTTPS 加的这一层
传输层:   TCP
网络层:   IP

TLS 的作用:

  • 加密:防止数据被窃听

  • 完整性:防止数据被篡改

  • 身份验证:通过证书确认服务器身份

3.2 数据交换格式

前后端之间传递的数据需要统一格式,最常用的是 JSON

复制代码
{
  "code": 200,
  "message": "success",
  "data": {
    "id": 1,
    "name": "张三",
    "email": "zhangsan@example.com"
  }
}

其他格式还有:XML、FormData、Protocol Buffers 等。

3.3 API 设计风格:RESTful

REST(Representational State Transfer)是一种 API 设计约定:

  • URL 表示资源/api/users/api/users/1

  • HTTP 方法表示操作:GET(查)、POST(增)、PUT(改)、DELETE(删)

  • 无状态:每次请求都携带完整信息,服务器不存储客户端状态

示例:

操作 HTTP 方法 URL 请求体
获取所有用户 GET /api/users
获取单个用户 GET /api/users/1
创建用户 POST /api/users {"name":"张三"}
修改用户 PUT /api/users/1 {"name":"李四"}
删除用户 DELETE /api/users/1
方式一:浏览器原生
复制代码
// Fetch API(现代标准)
fetch('/api/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: '张三' })
})
.then(response => response.json())
.then(data => console.log(data));
方式二:第三方库(Axios)
复制代码
axios.post('/api/users', { name: '张三' })
  .then(response => console.log(response.data));

3.5 同步 vs 异步通信

上面的 HTTP 请求-响应是同步的一次性通信 。但有些场景需要实时推送

方式 协议 说明 适用场景
轮询(Polling) HTTP 前端定时发请求 简单场景
长轮询(Long Polling) HTTP 服务器hold住请求直到有新数据 通知类
SSE HTTP 服务器单向推送 实时日志、股票
WebSocket WS/WSS 全双工双向通信 聊天、游戏、协同编辑
WebSocket 协议

WebSocket 的建立过程:

  1. 客户端发送一个特殊的 HTTP 请求(Upgrade 请求)

  2. 服务器同意升级,返回 101 Switching Protocols

  3. 此后双方通过同一个 TCP 连接进行双向实时通信

复制代码
客户端 → 服务器:
GET /chat HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
​
服务器 → 客户端:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
​
(之后就是 WebSocket 帧,不再是 HTTP 了)

四、后端部分

4.1 后端的职责

后端(服务器端)负责:

  • 接收请求:解析前端发来的 HTTP 请求

  • 业务逻辑:验证、计算、权限判断等

  • 数据存取:与数据库交互

  • 返回响应:将结果序列化(通常为 JSON)返回前端

4.2 后端架构

单体架构(Monolithic)

所有功能模块打包在一个应用中:

复制代码
┌─────────────────────────────────────┐
│            后端应用(单体)            │
│  ┌──────┐ ┌──────┐ ┌──────┐        │
│  │用户模块│ │订单模块│ │支付模块│       │
│  └──────┘ └──────┘ └──────┘        │
│  ┌─────────────────────────────┐    │
│  │       数据访问层(DAO/ORM)     │    │
│  └─────────────────────────────┘    │
└─────────────────────────────────────┘
                  │
              ┌───┴───┐
              │ 数据库  │
              └───────┘
微服务架构(Microservices)

每个功能拆分为独立的服务,通过网络通信:

复制代码
┌──────────┐  ┌──────────┐  ┌──────────┐
│ 用户服务   │  │ 订单服务   │  │ 支付服务   │
│  :8001    │  │  :8002    │  │  :8003    │
└─────┬────┘  └─────┬────┘  └─────┬────┘
      │             │             │
   ┌──┴──┐      ┌──┴──┐      ┌──┴──┐
   │用户DB│      │订单DB│      │支付DB│
   └─────┘      └─────┘      └─────┘

微服务之间的通信方式:

  • 同步:HTTP/REST、gRPC(基于 HTTP/2 + Protocol Buffers)

  • 异步:消息队列(RabbitMQ、Kafka

4.3 后端分层架构(MVC / 三层架构)

后端内部通常分为以下几层:

复制代码
HTTP 请求进入
     ↓
┌─────────────────────┐
│  Controller 层(控制器)│  ← 接收请求、参数校验、调用Service
└──────────┬──────────┘
           ↓
┌─────────────────────┐
│  Service 层(业务逻辑)  │  ← 核心业务处理、事务管理
└──────────┬──────────┘
           ↓
┌─────────────────────┐
│  DAO/Repository 层    │  ← 数据库操作(CRUD
│  (数据访问层)         │
└──────────┬──────────┘
           ↓
┌─────────────────────┐
│  数据库(MySQL等)      │
└─────────────────────┘

各层职责说明:

职责 示例
Controller 路由分发、参数解析、调用 Service @GetMapping("/users")
Service 业务逻辑、事务管理 判断用户是否存在、余额是否充足
DAO/Repository 与数据库交互 SELECT * FROM users WHERE id=1
Model/Entity 数据实体定义 User { id, name, email

4.4 一次完整请求的处理流程

以"用户注册"为例:

复制代码
1. 前端发送 POST /api/register, body: {name:"张三", password:"123456"}
2. 后端 Controller 接收请求,解析参数
3. Controller 调用 Service 层的 register() 方法
4. Service 层:
   a. 校验用户名是否已存在(调用 DAO 查询数据库)
   b. 密码加密(bcrypt)
   c. 调用 DAO 层插入新用户记录
5. DAO 层:拼接 SQL,通过数据库驱动发送到数据库
6. 数据库执行 INSERT 语句,返回结果
7. DAO 层将结果封装为对象返回给 Service
8. Service 返回给 Controller
9. Controller 将结果序列化为 JSON,返回 HTTP 响应
10. 前端收到响应,显示"注册成

五、后端连接数据库

5.1 数据库分类

类型 代表产品 数据模型 适用场景
关系型数据库 (RDBMS) MySQL、PostgreSQL、Oracle、SQL Server 表(行和列) 事务性业务、结构化数据
文档型数据库 MongoDB JSON 文档 灵活 schema、内容管理
键值数据库 Redis Key-Value 缓存、会话存储
列族数据库 Cassandra、HBase 列族 大数据、时序数据
图数据库 Neo4j 节点+边 社交关系、推荐系统

5.2 后端连接数据库的原理

5.2.1 数据库驱动(Database Driver)

后端应用不能直接与数据库"对话",需要通过数据库驱动(也叫数据库连接器/客户端库)。

驱动的作用:

  • 将应用层的操作(如 SQL 语句)翻译成数据库私有协议

  • 管理与数据库的 TCP 连接

  • 处理认证、加密、数据类型转换

不同数据库有不同的通信协议:

数据库 协议 默认端口
MySQL MySQL Protocol(基于 TCP) 3306
PostgreSQL PostgreSQL Protocol(基于 TCP) 5432
MongoDB MongoDB Wire Protocol(基于 TCP) 27017
Redis RESP(Redis Serialization Protocol,基于 TCP) 6379
SQL Server TDS(Tabular Data Stream,基于 TCP) 1433
Oracle Oracle Net / TNS(基于 TCP) 1521
5.2.2 连接建立过程

以 MySQL 为例:

复制代码
1. 后端应用通过驱动向数据库服务器的 3306 端口发起 TCP 连接
2. TCP 三次握手建立连接
3. MySQL 服务器发送握手包(Handshake Packet),包含:
   - 协议版本
   - 服务器版本
   - 认证方式
   - 加密种子(Salt)
4. 客户端(驱动)发送认证包:
   - 用户名
   - 加密后的密码(password + salt 经过 SHA 运算)
   - 指定要使用的数据库
5. 服务器验证通过,返回 OK 包
6. 连接建立完成,可以发送 SQL 命
5.2.3 SQL 命令执行过程
复制代码
后端应用
   │
   │ 调用: connection.query("SELECT * FROM users WHERE id = 1")
   ↓
数据库驱动
   │
   │ 将 SQL 封装为 MySQL 协议的 COM_QUERY 包
   │ 通过 TCP 发送给 MySQL 服务器
   ↓
MySQL 服务器
   │
   │ 1. 解析 SQL(Parser)
   │ 2. 优化查询计划(Optimizer)
   │ 3. 执行查询(Executor)
   │ 4. 从存储引擎读取数据(如 InnoDB)
   │ 5. 将结果封装为 Result Set 包
   │ 6. 通过 TCP 返回
   ↓
数据库驱动
   │
   │ 解析 Result Set 包
   │ 转换为编程语言中的对象/数组
   ↓
后端应用
   │
   │ 得到 [{id: 1, name: "张三", email: "zhangsan@example.com"}]
为什么需要连接池?

每次请求都新建数据库连接,开销很大:

  • TCP 三次握手

  • 数据库认证

  • 分配资源

  • 用完后释放

连接池预先创建一批连接并复用:

复制代码
┌────────────────────────────────┐
│         连接池(Connection Pool) │
│                                │
│   ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
│   │连接1│ │连接2│ │连接3│ │连接4│ │     ←  预先创建好的空闲连接
│   │空闲 │ │使用中│ │空闲 │ │空闲 │ │
│   └────┘ └────┘ └────┘ └────┘ │
│                                │
│  最小连接数: 4    最大连接数: 20   │
│  空闲超时: 30min   最大等待: 5s  │
└────────────────────────────────┘
         │  │  │  │
         ↓  ↓  ↓  ↓
┌────────────────────────────────┐
│        MySQL 服务器              │
└────────────────────────────────┘

工作流程:

  1. 应用请求数据库连接 → 从池中取一个空闲连接

  2. 使用连接执行 SQL

  3. 使用完毕 → 归还连接到池中(不关闭)

  4. 池满时 → 新请求排队等待或扩容(到最大连接数

ORM(Object-Relational Mapping)让开发者用面向对象的方式操作数据库,而不需要手写 SQL。

复制代码
数据库表:users
+----+--------+-----+
| id | name   | age |
+----+--------+-----+
| 1  | 张三   | 25  |
+----+--------+-----+

                ↕  ORM 映射

编程语言对象:
class User {
    int id = 1;
    String name = "张三";
    int age = 25;
}

ORM 的分层位置:

复制代码
Controller → Service → ORM(Repository/DAO) → 数据库驱动 → 数据库
                        ↑
                   开发者写对象操作
                   ORM 自动生成 SQL

各语言主流 ORM:

语言 ORM 框架
Java Hibernate、MyBatis、JPA
Python SQLAlchemy、Django ORM
Node.js Sequelize、TypeORM、Prisma
Go GORM
C# Entity Framework

六、认证与会话管理

前后端交互中的一大问题:HTTP 是无状态的。服务器不会记住"这个请求是谁发的"。

复制代码
1. 用户登录:POST /login {username, password}
2. 服务器验证通过,在服务端创建 Session 对象(存在内存/Redis中)
   Session: { id: "abc123", userId: 1, role: "admin" }
3. 服务器在响应头设置:Set-Cookie: sessionId=abc123
4. 浏览器自动保存 Cookie
5. 之后每次请求,浏览器自动携带:Cookie: sessionId=abc123
6. 服务器通过 sessionId 查找 Session,确认用户身份

6.2 JWT(JSON Web Token)方式

复制代码
1. 用户登录:POST /login {username, password}
2. 服务器验证通过,生成 JWT Token:
   Header.Payload.Signature
   eyJhbGc...  (Base64编码的JSON,包含用户信息+签名)
3. 返回 Token 给前端
4. 前端将 Token 存在 localStorage 或 Cookie 中
5. 之后每次请求在 Header 中携带:
   Authorization: Bearer eyJhbGc...
6. 服务器验证 Token 签名,解析出用户信息(无需查数据库/Session存储)

七、中间件与反向代理

7.1 Nginx 反向代理

在实际部署中,用户的请求通常不会直接到达后端应用,而是先经过 Nginx 等反向代理:

复制代码
用户浏览器
     │
     ↓
┌─────────┐
│  Nginx   │  ← 反向代理 + 负载均衡 + 静态资源服务 + HTTPS终止
│ (端口80/443) │
└────┬────┘
     │
     ├────→ 后端实例1 (端口8080)
     ├────→ 后端实例2 (端口8080)
     └────→ 后端实例3 (端口8080)

Nginx 的职责:

功能 说明
反向代理 隐藏后端服务器,统一入口
负载均衡 将请求分发到多个后端实例(轮询、加权、IP Hash等)
静态资源服务 直接返回 HTML/CSS/JS/图片,无需经过后端
HTTPS 终止 在 Nginx 层处理 TLS,后端只需处理 HTTP
缓存 缓存后端响应,减少后端压力

八、缓存架构

8.1 多级缓存

为了提高性能,数据的读取通常经过多级缓存:

复制代码
浏览器缓存(HTTP Cache)
       ↓ 未命中
CDN 缓存(地理就近节点)
       ↓ 未命中
Nginx 缓存(反向代理层)
       ↓ 未命中
应用层缓存(如本地 HashMap)
       ↓ 未命中
分布式缓存(Redis / Memcached)
       ↓ 未命中
数据库(MySQL)

8.2 Redis 缓存的典型用法

复制代码
读取流程:
1. 先查 Redis 缓存
2. 缓存命中 → 直接返回
3. 缓存未命中 → 查数据库 → 将结果写入 Redis → 返回
​
后端代码伪逻辑:
function getUser(id) {
    // 1. 查缓存
    let user = redis.get("user:" + id);
    if (user) return user;
    
    // 2. 查数据库
    user = db.query("SELECT * FROM users WHERE id = ?", id);
    
    // 3. 写缓存(设置过期时间)
    redis.set("user:" + id, user, expire=3600);
    
    return user;
}

九、完整架构总览

把以上所有组件组合起来,一个典型的现代 Web 应用架构如下:

复制代码
                        ┌─────────────┐
                        │   用户浏览器   │
                        └──────┬──────┘
                               │ HTTPS
                        ┌──────┴──────┐
                        │     CDN      │  ← 静态资源加速
                        └──────┬──────┘
                               │
                        ┌──────┴──────┐
                        │    Nginx     │  ← 反向代理 / 负载均衡
                        │  (端口 443)   │     / HTTPS 终止
                        └──┬───┬───┬──┘
                           │   │   │
                    ┌──────┘   │   └──────┐
                    ↓          ↓          ↓
              ┌─────────┐ ┌────────┐ ┌─────────┐
              │ 后端实例1 │ │后端实例2│ │ 后端实例3 │
              │ (8080)   │ │(8080)  │ │ (8080)   │
              └────┬────┘ └───┬────┘ └────┬────┘
                   │          │           │
              ┌────┴──────────┴───────────┴────┐
              │                                 │
        ┌─────┴─────┐                   ┌──────┴──────┐
        │   Redis     │                   │    MySQL     │
        │  (缓存)     │                   │  (主数据库)   │
        │  端口 6379   │                   │  端口 3306    │
        └────────────┘                   └──────┬──────┘
                                                │ 主从复制
                                         ┌──────┴──────┐
                                         │ MySQL 从库    │
                                         │ (读库)        │
                                         └─────────────┘

十、涉及的协议汇总

层次 协议 作用
应用层 HTTP/1.1、HTTP/2、HTTP/3 前后端通信的基础协议
应用层 HTTPS(HTTP + TLS) 加密的 HTTP 通信
应用层 WebSocket(WS/WSS) 全双工实时通信
应用层 DNS 域名解析为 IP
应用层 gRPC(基于 HTTP/2) 微服务间高效通信
安全层 TLS 1.2 / 1.3 传输层安全加密
传输层 TCP 可靠的字节流传输
传输层 UDP 不可靠但快速传输(HTTP/3 基于 QUIC/UDP)
网络层 IP(IPv4/IPv6) 网络寻址和路由
数据库协议 MySQL Protocol MySQL 客户端-服务器通信
数据库协议 PostgreSQL Protocol PostgreSQL 通信
数据库协议 RESP Redis 通信
数据库协议 MongoDB Wire Protocol MongoDB 通信
序列化协议 JSON 前后端数据交换格式
序列化协议 Protocol Buffers gRPC 数据序列化

十一、数据流动全景

一个用户点击"提交订单"按钮,数据的完整流动路径:

复制代码
1.  用户点击按钮
2.  浏览器 JavaScript 收集表单数据,构造 JSON
3.  JavaScript 调用 fetch/axios 发起 HTTPS POST 请求
4.  浏览器进行 DNS 解析,获取服务器 IP
5.  TCP 三次握手建立连接
6.  TLS 握手建立加密通道
7.  HTTP 请求数据经 TLS 加密后通过 TCP 发送
8.  到达 CDN(通常只处理静态资源,API 请求直接转发)
9.  到达 Nginx 反向代理
10. Nginx 终止 TLS(解密),按负载均衡策略选择一个后端实例
11. Nginx 以 HTTP 明文将请求转发给后端实例(内网通信)
12. 后端 Controller 接收请求,解析 JSON
13. Controller 调用 Service 层
14. Service 层处理业务逻辑:
    a. 调用 Redis 检查库存缓存
    b. Redis 通过 RESP 协议返回缓存数据
    c. 调用 DAO 层查询/写入 MySQL
15. DAO 层通过连接池获取数据库连接
16. 数据库驱动将 SQL 封装为 MySQL Protocol 包
17. 通过 TCP 发送到 MySQL 服务器(端口 3306)
18. MySQL 解析 SQL → 优化 → 执行 → 写入 InnoDB 存储引擎
19. MySQL 返回执行结果
20. 数据沿原路层层返回
21. 后端返回 JSON 响应给 Nginx
22. Nginx 将响应通过 HTTPS 返回给浏览器
23. 浏览器接收并解密响应
24. JavaScript 解析 JSON
25. 更新页面 DOM,显示"下单成功"

总结

环节 关键技术 核心协议
域名解析 DNS 服务器 DNS(UDP/TCP 53)
前后端通信 RESTful API / GraphQL HTTP/HTTPS(TCP 80/443)
实时通信 WebSocket WS/WSS(TCP)
请求转发 Nginx 反向代理 HTTP
后端处理 MVC 分层架构 ---
缓存 Redis RESP(TCP 6379)
数据库读写 连接池 + ORM + SQL MySQL Protocol(TCP 3306)
微服务通信 gRPC / 消息队列 HTTP/2 + Protobuf / AMQP
安全传输 TLS 证书 TLS 1.2/1.3

更多精彩内容可以关注:别催小唐敲代码

相关推荐
Yungoal2 小时前
计算机存储体系
架构
工作log2 小时前
AI点餐助手架构全流程解析
java·开发语言·微服务·架构
SelectDB技术团队2 小时前
PostgreSQL + Apache Doris:构建用于实时分析的 HTAP 架构
数据库·postgresql·架构·实时数仓·湖仓一体·apache doris·selectdb
九河云2 小时前
云供应链安全:第三方 SaaS 服务的风险评估与管控
大数据·运维·安全·架构·数字化转型
Volunteer Technology10 小时前
架构面试题(一)
开发语言·架构·php
张张123y11 小时前
RAG从0到1学习:技术架构、项目实践与面试指南
人工智能·python·学习·面试·架构·langchain·transformer
sg_knight11 小时前
如何用 Claude Code 做大型项目重构与架构优化
java·重构·架构·llm·claude·code·claude-code
老鱼说AI12 小时前
CUDA架构与高性能程序设计:异构数据并行计算
开发语言·c++·人工智能·算法·架构·cuda
小箌12 小时前
springboot_03
spring boot·后端·状态模式