浏览器输入 URL 回车后会经历哪些步骤?

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 本文首发于微信公众号“前端徐徐”,详细解析了从在浏览器中输入URL到页面完全呈现的全过程,涵盖检查缓存、URL解析、DNS解析、TCP连接、HTTP请求、服务器响应、浏览器处理响应、页面解析与渲染、关闭TCP连接等关键步骤。通过这些步骤,帮助读者深入了解互联网的工作原理,提升网站性能和用户体验。

本文首发微信公众号:前端徐徐。

前言

其实这个问题成了老生常谈的问题了,但是里面的内容太多,这里做出一些简单的分析,带你看清每一步的步骤。 在浏览器中输入一个 URL 并按下回车键时,其实启动了一系列复杂的过程,经历了这些过程后你才能够在屏幕上看到并与网页内容进行交互。这个过程涉及从解析 URL 到最终呈现页面的多个步骤。了解这些步骤不仅有助于更好地理解互联网的工作原理,还能帮助我们优化网站性能和用户体验,后期打算把每一步做个详解,然后形成一系列文章,敬请期待。
话不多说,开始进入正题,下图表现了整个大的过程,然后会对每个过程做一下简单的梳理。

检查缓存

当浏览当浏览器输入一个 URL 时,它会先检查本地缓存,看请求的资源是否已经存在并且还在有效期内。这是为了加速页面加载速度。
具体过程是:

  1. 浏览器通过哈希 URL 计算出一个唯一的 key,用于查找缓存。
  2. 在浏览器缓存(内存或本地磁盘)中根据该 key 查找资源。
  3. 如果找到了缓存资源,并且没有超过该资源的最大缓存有效期,则直接使用缓存。
  4. 如果没有找到或缓存已过期,则需要发起网络请求,从服务器获取资源。
  5. 将新获取的资源写入缓存,供下次使用。

这一步主要目的是利用缓存机制加速二次加载,不需要每次都重新获取资源,提高页面性能。

对 URL 进行分析

当浏览器缓存中没有请求的 URL 对应的资源时,浏览器会对该 URL 进行语法解析,主要目的是提取出发起请求所需的关键信息,包括:

  1. 协议(Protocol): 如 HTTP、HTTPS、FTP 等,标识使用什么应用层协议和该资源的传输方式。
  2. 域名(Domain name): 资源所在服务器的域名地址,如 www.example.com。
  3. 端口 (Port): 服务器开启的端口号,默认 80 端口(HTTP) 和 443 端口(HTTPS)。
  4. 路径(Path): 访问资源在服务器上的具体路径与文件名。
  5. 参数(Parameters): 请求的参数,以键值对的形式附在 URL 路径的后面。
  6. 锚点(Anchor): 页面内部锚链接位置。

通过解析 URL 字符串,浏览器可以区分出用户想要联系的服务器地址与路径,从而为后续步骤如 DNS 解析、建立连接做准备。这一步解析主要依据 RFC 3986 标准来实现,浏览器会逐一检验 URL 各部分的格式及长度限制,提取所需信息。如果 URL 不符合语法标准,将无法被浏览器正确解析与处理。
这一步的目的是提取发起网络请求所必须的关键参数,为后续流程做准备。URL 的语法规范定义也使得这一解析过程得以标准化。

域名解析

在浏览器解析出 URL 中的域名后,下一步就是将域名转换成 IP 地址,这个过程称为域名解析(DNS 解析)。

  1. 浏览器检查本地 DNS 缓存,看是否已经有解析过这个域名对应的 IP 地址。
  2. 如果缓存中没有,浏览器则向操作系统的本地 DNS 解析器发起域名解析请求。
  3. 本地 DNS 解析器也会先在其缓存中查找,如果未命中,则递归地向根 DNS 服务器发起解析请求。
  4. 根服务器返回负责这个域的顶级 DNS 服务器地址。
  5. 本地解析器向顶级 DNS 服务器发请求,重复递归查询,直到获取域名的权威 DNS 服务器。
  6. 权威 DNS 服务器持有该域名的记录,将对应的 IP 地址返回给本地解析器。
  7. 本地解析器将结果缓存,并返回 IP 地址给浏览器。

通过这样的递归查询,域名最终被转换成了用于建立连接的 IP 地址。这个过程遵循 DNS 协议,以分布式的 DNS 服务器实现域名与 IP 地址的映射。
这一步的目的是通过可读的域名取得实际的 IP 地址,然后才能进行后续的网络通信。它也实现了域名和 IP 的解耦,使得网络通信更灵活易用。

TCP 连接

获取到目标网站的 IP 地址后,浏览器会与其建立 TCP 连接,这个过程称为“三次握手”:

  1. 客户端向服务器的端口发出连接请求报文,设置 SYN=1,随机选择一个初始序列号 seq=x。
  2. 服务器收到 syn 报文,如果同意连接,则向客户端返回确认报文,确认号 ack=x+1,同时也选择一个随机序号 seq=y,设置 SYN=1。
  3. 客户端收到确认报文,再向服务器发确认报文,确认号 ack=y+1。

完成三次握手,连接建立,客户端与服务器正式开始 TCP 通信。
三次握手的目的是:

  1. 确定双方都准备好了通信,避免一方没准备好就被动收到数据。
  2. 同步双方的序列号,用于后续的数据传输。
  3. 交换 TCP 窗口大小信息。

需要注意的是,挥手在网络可靠性差的情况下可能会重复发送,直至取得响应或超时放弃。
三次握手需要连接建立前的预先交涉,但可以防止各种异常情况的发生,保证双方准备就绪后再开始传输数据,使得 TCP 连接可靠。

发送 HTTP 请求

浏览器在 TCP 连接建立后会向服务器发送 HTTP 请求:

  1. 构造 HTTP 请求报文:浏览器会根据请求的资源和 purpose,决定采用 GET,POST 还是其他方法,并根据情况构造请求路径,填写 HTTP 版本等字段。
  2. 请求行:首先是请求行,包含方法、请求 URL 和 HTTP 版本,例如: GET /index.html HTTP/1.1
  3. 请求头部:然后是各种请求头部,包含请求上下文相关的元信息,如 Host, User-Agent, Accept 等。
  4. 请求体:最后是请求体,POST 方法时才有,包含要发送的数据。
  5. 发送请求:浏览器经过 TCP 连接发送构造的 HTTP 请求给服务器。
  6. 等待响应:发送请求后,浏览器等待服务器返回 HTTP 响应。
  7. 获取响应:服务器处理请求后,会返回包含响应状态码、响应头部、响应体的 HTTP 响应内容。
  8. 解析响应:浏览器接收到响应后,会根据状态码和内容来决定下一步行为。

以上就是浏览器构造 HTTP 请求并发送给服务器的基本过程。

服务器接收并处理请求

服务器处理浏览器发来的 HTTP 请求并返回响应的详细步骤如下:

  1. 服务器上的 Web 服务端软件 (如 Apache、Nginx 等) 接收到浏览器请求。
  2. Web 服务器对请求进行解析,提取出请求方法、URL、协议版本等信息。
  3. 检查请求的语法是否正确,请求资源是否存在。
  4. 调用相应的后端应用程序或者脚本语言 (如 PHP、Python 等) 来生成响应内容。
  5. 后端程序读取请求资源内容,从文件系统、数据库或通过计算生成。
  6. Web 服务器将响应内容封装到 HTTP 响应报文。
  7. 设置状态码 (200、404 等) 表示请求结果。
  8. 添加响应头,包含内容类型、长度等元信息。
  9. 把响应报文发送给浏览器。
  10. 对于动态内容,还可以在响应体中加入 Cookies 用于会话跟踪。
  11. 对于 POST 请求,服务器还要读取并处理请求体中的数据。
  12. 服务器会缓存静态资源,加速重复请求的响应。
  13. 根据情况,可能会重定向到其他 URL 地址。

以上涵盖了服务器从接收请求到发送响应的基本过程,实际上可能还更复杂,涉及权限、数据库、性能优化等处理。

浏览器处理响应

检查响应

浏览器接收到服务器响应后,会按以下步骤处理:

  1. 检查响应状态码

2XX 范围表示成功,常见的有:

  • 200 OK - 请求成功
  • 206 Partial Content - 断点下载
  • 304 Not Modified - 资源未修改,直接使用缓存

3XX 范围表示重定向,Location 头指向新地址:

  • 301 Moved Permanently - 永久重定向
  • 302 Found - 临时重定向

4XX 客户端错误,如:

  • 400 Bad Request - 请求语法错误
  • 404 Not Found - 找不到资源
  • 403 Forbidden - 没有权限

5XX 服务器错误:

  • 500 Internal Server Error - 服务器内部错误
  • 503 Service Unavailable - 服务不可用
  1. 检查响应头信息

解析响应头,查看内容长度、类型、编码方式等元信息。

  1. 根据状态码决定下一步行为

如果是成功 2XX 代码,则继续处理响应体。3XX 代码则重新请求重定向地址。4XX 和 5XX 为错误码时要给用户错误提示。

  1. 读取并处理响应体

成功响应后,浏览器会根据响应头给定的内容类型解析响应体,并展示内容或者保存文件等。
这样浏览器就可以根据服务器返回的 HTTP 响应状态码和内容来决定下一步的处理,完成请求资源的获取。

根据资源类型分别处理

如果服务器返回的响应状态码表示正常 (2XX),浏览器会根据响应头中的内容类型(Content-Type) 来解析响应体并进行处理,常见的有:

  1. text/html - HTML 文档
  • 浏览器会解析 HTML 内容,构建 DOM 树,加载解析过程中遇到的资源
  1. image/png、image/jpeg 等 - 图片
  • 浏览器会解析出图片内容,并显示在页面中
  1. video/mp4 等 - 视频文件
  • 浏览器会调用视频播放器开始播放
  1. application/javascript - Javascript 脚本
  • 浏览器会执行脚本来修改 DOM 和行为
  1. text/css - CSS 样式表
  • 浏览器会解析 CSS 来渲染页面
  1. application/json - JSON 数据
  • 浏览器会解析 JSON 字符串并触发相应 callback
  1. text/plain - 文本内容
  • 浏览器会直接显示文本
  1. application/octet-stream - 二进制文件
  • 浏览器会下载文件并存储在本地

不同类型的响应,浏览器会有不同的解析方式和处理流程,最大程度地恢复资源的原始内容和行为。

页面解析 & 渲染

这里主要涉及的是浏览器响应成功后获取到 HTML 文档后的步骤:

  1. 获取 HTML 文档:从响应内容中获取到要解析的 HTML 文档
  2. 解析 HTML 构建 DOM 树
  1. 浏览器使用解析器 (parser) 读取 HTML 代码,分割成标记 (tag)、文本、注释等标记化(tokenized) 后的 tokens。
  2. 根据 HTML 语法构建 DOM 节点树。遇到开始标签创建元素节点,遇到文本创建文本节点,注释也会创建节点。
  3. 每个节点是一个对象,保存了标签名、属性、内容等信息。节点之间根据嵌套关系建立父子关系。
  4. 其中为根节点,为子节点。其他各级节点也逐步添加为树结构。
  5. HTML 的 attribute 会被解析为节点的属性。类似 id、class 等。
  6. 构建完成后形成一颗以 HTML 标签为节点的 DOM 树。
  7. 这个树描述了 HTML 文档的节点关系和内容信息,是后续 CSS 和 JS 可以访问的表示形式。
  8. 浏览器使用 DOM API 可以访问或修改 DOM 节点树的内容。
  1. 解析 CSS 构建 CSSOM 树
  1. 浏览器使用 CSS 解析器读取 CSS 代码,按照 CSS 语法规则分割为标记化的 tokens。
  2. 浏览器会根据 CSS 规则生成对应样式规则 (style rule) 的节点对象。
  3. 每个节点包含了 CSS 选择器和对应声明的样式信息。
  4. 节点之间根据 CSS 的继承、层叠等规则建立树结构关系。
  5. 根节点是代表全局样式信息的根规则集(Root Style Sheet)。
  6. 每个规则下面连接具有对应选择器的规则节点。
  7. 构建完成后形成 CSS 对象模型 (CSSOM) 树结构。
  8. 树结构中每个节点代表一个可复用的 CSS 声明对象。
  9. 通过 CSSOM API 可以访问读取节点的样式信息。
  1. 构建 Render 树
  1. 浏览器将 DOM 树和 CSSOM 树结合,生成一个 Render 树(Render Tree)。
  2. Render 树中的每个节点称为 RenderObject,包含内容、样式和布局信息。
  3. 对于 DOM 上不影响渲染的节点,如 script、meta,在 Render 树中不会创建对应的 RenderObject。
  4. 对于每个可见的 DOM 节点,根据匹配的 CSS 规则,生成带有样式信息的 RenderObject。
  5. 如果一个 DOM 节点被多个规则匹配,则根据 CSS 的层叠、继承、优先级等计算出一个综合样式。
  6. Render 树的根节点是代表视窗的 RenderObject。
  7. 子节点层层添加,形成代表页面结构与样式信息的 Render 树。
  8. Render 树准确描述了页面的视觉表示与布局信息,用于下一步的布局和绘制。
  9. 当 DOM 或 CSSOM 更新时,可以增量更新 Render 树,无需全部重新构建。
  1. 布局(Layout)
  1. 从 Render 树的 Root 节点开始遍历所有对象,计算布局。
  2. 根据 RenderObject 的类型、属性,确定其显示模式,如块状或内联。
  3. 对块元素,计算其精确的位置、宽高等几何信息。
  4. 对内联元素,计算其在当前行内的定位。
  5. 父节点会影响子节点的布局,布局受包含块大小的影响。
  6. absolut positioning 脱离普通流,根据 offset parent 定位。
  7. 浮动元素也会脱离普通流,但会影响兄弟元素布局。
  8. 创建行盒、块盒等箱模型表示内容区域。确定 padding、margin、border 大小。
  9. 计算滚动溢出、自动换行等,移动或裁剪元素。
  10. 布局完成后,每个 RenderObject 都确定了页面中的坐标位置。
  1. 绘制(Painting)
  1. 根据 Render 树和 Layout 结果遍历所有 RenderObject。
  2. 根据节点类型和样式信息,绘制不同的 UI 内容,如文本、颜色、图像等。
  3. 对文本内容,根据 font 样式绘制文字图形。
  4. 对图片和视频,根据 src 绘制图像位图。
  5. 对颜色和背景,填充绘制颜色矩形区域。
  6. 绘制完成后,内容从逻辑坐标映射到设备坐标(屏幕像素)。
  7. 由上至下,由左至右顺序绘制,遵循层叠顺序。
  8. 创建堆叠上下文 (Stacking Contexts) 表示层叠和 z 轴次序。
  9. 绘制过程遵循各种 CSS 属性,如透明度、变形等效果。
  10. 使用 GPU 加速绘制提高性能。
  11. 绘制内容到设备缓冲区(Framebuffer),并显示在屏幕上。
  1. 合成(Compositing)
  1. 浏览器可能使用多个层 (Layer) 来分别绘制页面中的不同部分,以提高效率。
  2. 这些层需要按照正确顺序叠加到一起,以表示 DOM 层叠顺序。
  3. 根据堆叠上下文 (Stacking Contexts) 的 z-index 值决定层的堆叠顺序。
  4. 合成步骤会将这些层合并到最终的图层组合中。
  5. 如果某层需要透明效果,该图层需要与下层进行混合。
  6. 使用 GPU 上的复合器 (Compositor) 来进行图层的合成。
  7. 将合成的位图最终绘制输出到显示环节。
  8. 合成步骤还会考虑页面的动画、转换、阴影等效果。
  9. 如果内容变更,只需要重新绘制变更的层,而不需要全部重绘。
  1. 更新渲染树和重绘
  1. JS 或用户交互可能会修改 DOM 树,也可能会变更 CSS 样式。
  2. 浏览器会监听这些变化,比如元素内容改变、样式表修改等。
  3. 当发生变化时,需要重新构建渲染树来反映更新后的状态。
  4. 对于影响渲染的 DOM 更改,需要同步更新渲染树对应的内容和样式信息。
  5. 如果仅仅是 CSS 规则变更,可以只更新渲染树中的样式信息。
  6. 对于新增或删除 DOM 节点,需要插入或删除对应渲染对象。
  7. 构建好新的渲染树后,进行后续的布局和绘制流程。
  8. 绘制时可能只需要重绘受变更影响的部分渲染树分支。
  9. 浏览器会尽量只重新绘制变更的部分,以提高效率。
  10. 完成后在界面上显示新的更新渲染结果。

以上是页面渲染的基本流程。

关闭 TCP 连接

浏览器与服务器建立 TCP 连接后,当 HTTP 请求响应全部完成时,它们会四次挥手关闭连接:

  1. 浏览器发送一个 FIN 标志位请求,表示客户端没有数据发送了,要关闭发送方向。
  2. 服务器接收到 FIN 后,发送一个 ACK 确认包,确认序号为收到序号 +1。
  3. 服务器发送自己的 FIN,表示服务端没有数据发送了,关闭发送方向。
  4. 浏览器收到服务器的 FIN 后,浏览器发送 ACK 确认包,确认序号再次 +1。

这样四次挥手完成后,浏览器和服务器都没有数据要发送了,连接关闭。
关闭连接的目的是:

  1. 通知对方我已经没有数据要发送了。
  2. 确认对方知道我要关闭连接了。
  3. 同意对方也可以关闭连接了。
  4. 对方确认知道我要关闭连接。

四次挥手的作用是保证双方都没有数据在网络中传输时,才可以安全关闭连接,防止数据丢失。
只有当浏览器和服务器都没有需要 TCP 连接进行传输的数据时,才可以进行四次挥手关闭连接,节省系统资源。

结语

上面就是整个过程的梳理,整个过程从解析 URL 到最终呈现页面,涉及多个复杂的步骤和技术细节。理解这些步骤不仅帮助我们更好地理解互联网和浏览器的工作原理,还能指导开发人员进行性能优化,提供更流畅的用户体验。无论是通过减少 DNS 查找时间、优化 HTTP 请求、还是改进 JavaScript 执行效率,这些知识都能在实际应用中发挥重要作用。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
4天前
|
缓存 网络协议 JavaScript
浏览器输入url之后最后网页渲染出来经过了什么
【10月更文挑战第31天】从浏览器输入 URL 到网页渲染出来是一个涉及多个环节和技术的复杂过程,每个环节都对最终的网页显示效果和用户体验有着重要的影响。
16 3
|
7天前
|
存储 缓存 网络协议
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点,GET、POST的区别,Cookie与Session
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点、状态码、报文格式,GET、POST的区别,DNS的解析过程、数字证书、Cookie与Session,对称加密和非对称加密
|
9天前
|
域名解析 缓存 网络协议
浏览器中输入URL返回页面过程(超级详细)、DNS域名解析服务,TCP三次握手、四次挥手
浏览器中输入URL返回页面过程(超级详细)、DNS域名解析服务,TCP三次握手、四次挥手
|
1月前
|
缓存 网络协议 前端开发
浏览器输入一个URL后,发生了什么?
浏览器输入一个URL后,发生了什么?
25 1
|
3月前
|
网络协议 前端开发 JavaScript
浏览器加载网页的幕后之旅:从URL到页面展示详解
【8月更文挑战第31天】当在浏览器地址栏输入URL并回车后,一系列复杂过程随即启动,包括DNS解析、TCP连接建立、HTTP请求发送、服务器请求处理及响应返回,最后是浏览器页面渲染。这一流程涉及网络通信、服务器处理和客户端渲染等多个环节。通过示例代码,本文详细解释了每个步骤,帮助读者深入理解Web应用程序的工作机制,从而在开发过程中作出更优决策。
57 5
|
3月前
|
存储 API 网络架构
【Azure 存储服务】MP4视频放在Azure的Blob里面,用生成URL在浏览器中打开之后,视频可以正常播放却无法拖拽视频的进度
【Azure 存储服务】MP4视频放在Azure的Blob里面,用生成URL在浏览器中打开之后,视频可以正常播放却无法拖拽视频的进度
|
2月前
|
前端开发 JavaScript
前端JS截取url上的参数
文章介绍了两种前端JS获取URL参数的方法:手动截取封装和使用URLSearchParams。
46 0
|
3月前
|
开发框架 前端开发 .NET
Asp.net Webapi 的 Post 方法不能把参数加到 URL 中?试试这样写
Asp.net Webapi 的 Post 方法不能把参数加到 URL 中?试试这样写
|
3月前
|
Java
JAVA 获取 URL 指定参数的值
JAVA 获取 URL 指定参数的值
45 0
|
4月前
|
JavaScript 前端开发 数据格式
URL编码【详解】——Javascript对URL进行编码解码的三种方式的区别和使用场景,axios请求拦截器中对get请求的参数全部进行URL编码
URL编码【详解】——Javascript对URL进行编码解码的三种方式的区别和使用场景,axios请求拦截器中对get请求的参数全部进行URL编码
220 0