Skip to content

一个请求的完整旅程

前言

当你在浏览器里输入一个网址按下回车,到页面显示出来,中间到底发生了什么? 这个问题是面试经典题,更是理解整个 Web 架构的钥匙。搞懂这条链路,你就能理解前端、后端、网络、数据库是怎么协作的。

这篇文章会带你学什么?

学完这章后,你将获得:

  • 全链路视角:理解一个 HTTP 请求从发出到返回的完整过程
  • 各层职责认知:DNS、TCP、负载均衡、Web 服务器、应用服务器、数据库各自做什么
  • 问题定位能力:请求慢或失败时,知道从哪一层开始排查
  • 性能优化思路:每一层都有优化空间,知道优化点在哪里
章节内容核心概念
第 1 章浏览器发起请求DNS 解析、TCP 连接、HTTP 请求
第 2 章网络传输路由、CDN、负载均衡
第 3 章服务器处理Web 服务器、应用逻辑、数据库查询
第 4 章响应返回序列化、压缩、渲染
第 5 章全链路优化缓存、连接复用、异步处理

0. 全景图:一个请求经历了什么?

用一个比喻来理解:你在网上下单买书,这个过程和 HTTP 请求惊人地相似。

请求阶段买书类比技术对应
输入网址你说"我要去某某书店"浏览器解析 URL
DNS 解析查地图找到书店地址域名 → IP 地址
TCP 连接走到书店门口,推门进去三次握手建立连接
发送请求告诉店员"我要《xxx》这本书"HTTP 请求报文
服务器处理店员去仓库找书、查库存、算价格应用逻辑 + 数据库查询
返回响应店员把书递给你HTTP 响应报文
浏览器渲染你打开书开始阅读HTML/CSS/JS 解析渲染

1. 浏览器发起请求

1.1 URL 解析

当你输入 https://api.example.com/books?id=123 时,浏览器会把它拆解成几个部分:

部分含义
协议https用加密方式通信
域名api.example.com服务器的"名字"
路径/books要访问的资源
查询参数id=123附加条件

1.2 DNS 解析:域名 → IP 地址

计算机不认识域名,只认识 IP 地址(如 93.184.216.34)。DNS 就是互联网的"电话簿"。

浏览器缓存 → 系统缓存 → 路由器缓存 → ISP DNS → 根域名服务器
     ↓ 命中就直接用,不命中就往下查

DNS 缓存的意义

如果每次请求都从根域名服务器查起,全球互联网会被 DNS 查询压垮。所以每一层都有缓存,大部分请求在浏览器或系统层就能解析完成。

1.3 TCP 三次握手

找到 IP 地址后,浏览器需要和服务器"建立连接"。TCP 用三次握手确保双方都准备好了:

客户端 → 服务器:你好,我想连接(SYN)
服务器 → 客户端:好的,我准备好了(SYN + ACK)
客户端 → 服务器:收到,开始通信(ACK)

如果是 HTTPS,还需要额外的 TLS 握手来协商加密方式。

1.4 发送 HTTP 请求

连接建立后,浏览器发送 HTTP 请求报文:

http
GET /books?id=123 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer eyJhbGci...
User-Agent: Chrome/120.0
组成部分内容
请求行方法(GET)+ 路径 + 协议版本
请求头元信息:身份认证、期望的数据格式等
请求体POST/PUT 请求才有,携带要提交的数据

2. 网络传输:请求在路上

2.1 路由转发

请求离开你的电脑后,会经过多个路由器的转发,就像快递经过多个中转站:

你的电脑 → 家庭路由器 → 运营商网络 → 骨干网 → 目标机房

每个路由器根据 IP 地址决定"下一跳"往哪里转发。可以用 traceroute 命令查看请求经过了哪些节点。

2.2 CDN 加速

如果目标网站使用了 CDN(内容分发网络),请求可能不需要到达源服务器:

场景走向
请求静态资源(图片、CSS、JS)CDN 边缘节点直接返回
请求动态数据(API)穿透 CDN,到达源服务器

CDN 的本质是"把内容提前放到离用户最近的地方"。

2.3 负载均衡

大型网站不会只有一台服务器。负载均衡器负责把请求分配到多台服务器上:

用户请求 → 负载均衡器 → 服务器 A(30% 流量)
                      → 服务器 B(30% 流量)
                      → 服务器 C(40% 流量)

常见的分配策略:

策略原理适用场景
轮询依次分配服务器配置相同
加权轮询按权重分配服务器配置不同
IP 哈希同一用户固定到同一台需要会话保持
最少连接分给当前连接最少的请求处理时间差异大

3. 服务器处理:厨房里发生了什么

请求到达服务器后,会经过多层处理。

3.1 Web 服务器(Nginx / Apache)

第一个接收请求的通常是 Web 服务器,它负责:

职责说明
静态文件服务直接返回 HTML、CSS、JS、图片
反向代理把 API 请求转发给后端应用
SSL 终止处理 HTTPS 加密解密
请求过滤拦截恶意请求、限流

3.2 应用服务器处理

Web 服务器把请求转发给应用服务器(Node.js、Spring、Django 等),处理流程:

请求进入 → 中间件链 → 路由匹配 → 控制器 → 服务层 → 数据访问层

中间件做的事情:

  1. 解析请求体(JSON、表单数据)
  2. 验证身份(检查 Token)
  3. 检查权限(这个用户能访问这个接口吗?)
  4. 记录日志(谁在什么时候访问了什么)

3.3 数据库查询

大部分请求最终都要和数据库打交道:

应用代码:SELECT * FROM books WHERE id = 123

数据库引擎:解析 SQL → 查询优化 → 执行计划 → 读取数据

返回结果:{ id: 123, title: "xxx", price: 59.9 }

数据库是最常见的性能瓶颈

网络传输通常是毫秒级,应用逻辑也很快,但一个没有索引的数据库查询可能要几秒甚至几十秒。所以"慢请求"大概率是数据库查询慢。


4. 响应返回:数据的归途

4.1 构造 HTTP 响应

服务器处理完后,构造响应报文:

http
HTTP/1.1 200 OK
Content-Type: application/json
Content-Encoding: gzip
Cache-Control: max-age=3600

{"id": 123, "title": "xxx", "price": 59.9}
组成部分内容
状态行协议版本 + 状态码(200 成功、404 未找到、500 服务器错误)
响应头数据格式、缓存策略、压缩方式等
响应体实际的数据内容(JSON、HTML 等)

4.2 数据压缩

服务器通常会用 gzip 或 brotli 压缩响应体,减少传输量:

压缩算法压缩率速度
gzip约 70%
brotli约 80%较慢但压缩更好

一个 100KB 的 JSON,压缩后可能只有 20-30KB。

4.3 浏览器渲染

浏览器收到响应后:

  1. 解析 HTML → 构建 DOM 树
  2. 解析 CSS → 构建样式树
  3. 合并 → 生成渲染树
  4. 布局 → 计算每个元素的位置和大小
  5. 绘制 → 把像素画到屏幕上

5. 全链路优化:每一层都能更快

5.1 各层优化手段

层级优化手段效果
DNSDNS 预解析、使用快速 DNS 服务减少 DNS 查询时间
网络CDN、HTTP/2、连接复用减少传输延迟
服务器缓存(Redis)、异步处理减少处理时间
数据库索引、查询优化、读写分离减少查询时间
前端懒加载、代码分割、资源压缩减少渲染时间

5.2 缓存:最有效的优化

缓存存在于请求链路的每一层:

浏览器缓存 → CDN 缓存 → 反向代理缓存 → 应用缓存(Redis)→ 数据库缓存

缓存的本质

用空间换时间。把计算过的结果存起来,下次直接用,不用重新算。缓存命中率每提高 10%,系统性能可能提升数倍。

5.3 请求失败时的排查思路

现象可能的问题层排查方法
完全无响应DNS / 网络ping、nslookup
连接超时网络 / 服务器宕机telnet、curl
返回 4xx客户端请求有误检查 URL、参数、Token
返回 5xx服务器内部错误查看服务器日志
响应很慢数据库 / 应用逻辑查看慢查询日志、APM 工具

6. 总结

一个 HTTP 请求的完整旅程:

  1. 浏览器:解析 URL → DNS 查询 → TCP 连接 → 发送请求
  2. 网络:路由转发 → CDN 判断 → 负载均衡分发
  3. 服务器:Web 服务器接收 → 中间件处理 → 业务逻辑 → 数据库查询
  4. 返回:构造响应 → 压缩 → 网络传输 → 浏览器渲染

理解全链路的价值

当你能在脑中画出请求的完整链路时,遇到任何问题都能快速定位到是哪一层出了问题。这是从"初级开发"到"能独立排查问题"的关键跨越。


延伸阅读