互联网是如何工作的
建立一个关于互联网如何通过分层协议和基础设施连接客户端与服务器的心智模型
全局视角:请求生命周期
请求向下传递。
用户意图形成
- Internet 请求生命周期是一个按顺序协同工作的专门化层级序列。
- 每一层都解决一个不同的系统问题,并将责任传递给下一层。
- 看起来像一个单一动作的事情,实际上是在多个抽象层之上执行的结构化流水线。
详情
浏览器 → DNS → TCP → HTTP → 服务器 → 数据库 → 响应 → 渲染
从高层来看,一个 Web 请求不是单一动作,而是一条协同工作的系统链路。每一步都存在于解决一个特定问题:找到目标位置、建立通信、定义请求、处理逻辑、检索数据,以及返回结果。
DNS 回答 “这个服务位于哪里?” TCP 回答 “我们如何可靠地通信?” HTTP 回答 “到底请求的是什么?” Server 和 Database 回答 “系统应该计算并返回什么?”
这些层彼此独立运行,但按顺序协作。没有任何单个组件能理解整个系统——每个组件只执行自己的职责,然后把控制权传递给下一步。
对用户来说看起来是瞬时完成的事情,实际上是在毫秒内执行的一条结构化抽象流水线。
触发器:输入 URL
人类输入名称。网络需要数字路由标识。
- URL 是一个对用户友好的标签,而不是直接的网络地址。
- 浏览器会提取域名并为解析做准备。
- 在通信开始之前,域名必须先转换为 IP 地址。
详情
当用户输入一个 URL 时,浏览器做的不只是“打开一个页面”。它首先会解析输入内容,以识别协议(例如 HTTPS)、域名以及请求的路径。
计算机不能使用像 example.com 这样的域名来路由流量。网络使用的是 IP 地址,也就是数字标识符。
浏览器会检查本地缓存,看看是否已经知道该域名对应的 IP 地址。如果不知道,它就会发起 DNS 查询过程,将名称解析为可路由的 IP 地址。
只有在完成这一步转换之后,系统才能继续建立连接。
名称到 IP:DNS 解析
DNS 通过分层且全球分布的查询系统,将人类可读的域名转换为 IP 地址。
缓存命中:瞬时。 缓存未命中:完整遍历 DNS 层级。
- DNS 会把网站名称转换为计算机用于通信的数字 IP 地址。
- 查询会沿着不同的 DNS 服务器逐步进行,直到找到正确的地址。
详情
DNS 的设计目标是作为互联网的分布式目录。它不依赖单一的中心数据库,而是将职责分散到多个层级的服务器上,以支持全球规模的访问。
当某个域名在本地还未知时,递归解析器会开始查询过程。它首先联系根服务器,根服务器会指向正确的顶级域(Top-Level Domain, TLD)服务器,例如 .com 或 .org。然后,TLD 服务器会将解析器引导到该特定域名的权威名称服务器。
权威服务器会提供最终的 IP 地址。该地址会返回给客户端,使浏览器能够继续并与正确的目标建立网络连接。
这种分层设计让 DNS 保持有序、可扩展,并且能够支持每天数十亿次查询。
连接:TCP 握手
可靠通信只有在双方就对话如何进行达成一致之后才开始。
客户端
服务器
客户端:让我们同步吧!
- TCP 确保数据可靠且按正确顺序到达。
- 在发送数据之前,双方会执行一个三步握手。
- 这个握手用于确认就绪状态并同步序列号。
详情
TCP 不会立即开始发送应用数据。它首先通过一个三步过程建立连接:SYN → SYN-ACK → ACK。
客户端先发送一个 SYN(同步)消息来请求建立连接。服务器返回 SYN-ACK,确认请求并共享自己的起始序列号。然后客户端发送 ACK 来确认收到。此时,双方已经就初始序列号达成一致,并且知道对方已经准备就绪。
这个交换过程为可靠传输奠定了基础。TCP 会跟踪序列号、检测丢包、重传缺失的数据,并根据网络状况调整发送速度。
只有在完成这一步协调之后,实际的应用数据才会开始传输。
应用层:HTTP
HTTP 定义了客户端如何请求资源,以及服务器如何通过结构化的请求-响应协议进行响应。
- HTTP 定义了一种浏览器和服务器都同意遵循的通用语言。
- 它标准化了资源如何被请求,以及响应如何被格式化。
- 它把原始网络数据转化为有意义的操作,比如“获取这个页面”或“提交这个表单”。
详情
TCP 确保字节能够可靠传输,但它并不定义这些字节的含义。HTTP 位于 TCP 之上,为通信提供结构和语义。它定义了客户端如何请求某些内容,以及服务器如何响应。
HTTP 请求包括一个方法(例如 GET 或 POST)、描述元数据的 headers,以及可选的包含数据的 body。服务器会返回一个状态码、headers 和请求的内容。由于双方都遵循相同的规则,它们可以一致地解释消息。
HTTP 之所以重要,是因为 Internet 是一个共享系统。如果没有定义消息结构和意图的通用协议,浏览器和服务器就无法相互理解。HTTP 为 web 创建了这种共享语言。
它定义的是请求和返回的内容,而不是数据在网络中如何物理传输。
服务器内部
服务器之所以能工作,是因为操作系统管理硬件资源,而应用程序代码负责处理并响应请求。
传入请求
操作系统分配 CPU + 内存 → 应用执行逻辑
已发送响应
- 客户端请求到达后,会通过操作系统被传递给服务器程序。
- 操作系统分配 CPU 时间、内存和网络访问权限来处理该请求。
- 服务器应用程序执行逻辑并生成要返回的响应。
详情
当数据到达一台机器时,它不会自动“运行”。操作系统接收网络数据,并使用 sockets 将其定向到正确的进程。这就是请求到达服务器程序的方式。
然后,OS 会管理所需的资源。它调度 CPU 时间以便服务器能够执行,分配内存用于处理,并控制对文件或数据库的访问。如果没有操作系统协调这些资源,就无法安全或高效地处理多个请求。
一旦请求进入服务器进程,应用程序逻辑就开始接管。它会解析 HTTP 消息,执行所需的计算或数据库查询,并构造响应。
操作系统负责让执行成为可能。服务器应用程序定义行为。
数据库与持久化
数据库是一种旨在随着时间推移存储、组织并可靠检索应用数据的系统。
| ID | 名称 | 角色 |
|---|---|---|
| 21 | Alice | User |
| 22 | Brian | Admin |
| 23 | Cathy | User |
| 24 | Daniel | User |
| 25 | Eva | Admin |
- 数据库的存在是为了在单个程序执行之外持久保存数据。
- 它们会组织信息,使其能够被高效搜索和更新。
详情
应用会不断生成数据——用户账户、帖子、交易、日志和配置。如果这些数据只存在于内存中,那么程序每次重启时它们都会消失。数据库通过在磁盘或分布式系统上提供持久存储来解决这个问题。
但仅有存储还不够。数据必须是有结构且可查询的。数据库会将信息组织成表或集合,并提供查询语言,使应用能够检索特定记录,而不必手动扫描全部数据。
为了提升性能,数据库会使用索引——一种充当查找映射的专用数据结构。引擎不需要检查每一行,而是可以直接跳转到相关条目。
数据库至关重要,因为现代应用需要持久状态。没有数据库,每个请求都会彼此独立运行,不会记住之前发生过的事情。
性能层:缓存和 CDN
现代系统通过将频繁请求的内容存储在更靠近用户的位置来提升速度,而不是每次都重新计算。
- 缓存通过提供已存储的响应来避免重复计算。
- CDN 将内容按地理位置分发,以降低延迟和源站负载。
详情
当用户多次请求同一个资源时,从头重新计算是低效的。缓存通过存储响应副本来解决这个问题,这样后续请求就可以立即返回,而无需再次访问数据库或应用逻辑。
缓存存在于多个层级——浏览器内部、服务器上以及网络边缘。内容分发网络(CDN)通过将内容分发到地理上分散的数据中心,将这一理念扩展到全球范围。用户不再总是连接源站服务器,而是被路由到最近的边缘节点。
缩短物理距离可以降低网络延迟,减少重复计算可以降低服务器负载。这些优化结合起来,能够在大规模场景下显著提升响应时间。
不过,缓存数据可能会过期,因此系统必须在速度和数据新鲜度之间取得平衡。
故障点
在分层系统中,路径上的任何组件都可能失败,而整体体验取决于系统对这些故障的处理能力。
DNS
TCP
服务器
数据库
- 请求生命周期中的每一层都可能独立失败。
- 某个组件的故障可能会阻止整个请求完成。
- 可靠的系统会预见并恢复部分故障。
详情
由于 Internet 请求生命周期涵盖 DNS、传输、服务器和数据库,因此问题可能出现在任何阶段。如果 DNS 无法解析域名,连接就不会开始。如果网络丢包或 TCP 连接断开,通信就会中断。
即使请求已经到达服务器,故障仍然可能发生。服务器进程可能崩溃、内存耗尽,或者无法连接到数据库。缓慢或无响应的数据库会延迟整个响应。
分布式系统很少会一次性全部失败。相反,它们通常是部分失败——一次只影响一个区域、一个实例或一个依赖项。设计弹性系统需要在多个层面加入冗余、健康检查、重试和回退机制。
理解故障可能发生的位置,对于理解真实世界中的系统行为至关重要。
问题部分
1 / 5