HTTP请求流程:为什么很多站点第二次打开速度会很快?

215 阅读7分钟

HTTP协议,正是建立在 TCP 连接基础之上的。HTTP 是一种允许浏览器向服务器获取资源的协议,是 Web的基础,通常由浏览器发起请求,用来获取不同类型的文件,例如 HTML 文件、CSS 文件、JavaScript 文件、图片、视频等。此外,HTTP 也是浏览器使用最广的协议,所以要想学好浏览器就要先深入了解 HTTP。

浏览器端发起 HTTP 请求流程,如果在浏览器输入网址接下来浏览器会做哪些动作?

  1. 构建请求,浏览器构建请求行信息,构建好后,浏览器准备发起网络请求。

    GET /index.html HTTP1.1

  2. 查找缓存,在真正发起网络请求之前,浏览器会先在浏览器缓存中查询是否有要请求的文件。其中,浏览器缓存是一种在本地保存资源副本,以供下次请求时直接使用的技术。 当浏览器发现请求的资源已经在浏览器缓存中存有副本,它会拦截请求,返回该资源的副本,并直接结束请求,而不会再去源服务器重新下载。好处:缓解服务器端压力,提升性能(获取资源的耗时更短了); 对于网站来说,缓存是实现快速资源加载的重要组成部分。如果缓存查找失败,就会进入网络请求过程。
  3. 准备 IP 地址和端口,不过,先不急,在了解网络请求之前,我们需要先看看 HTTP 和 TCP 的关系。因为浏览器使用 HTTP 协议作为应用层协议,用来封装请求的文本信息;并使用 TCP/IP 作传输层协议将它发到网络上,所以在 HTTP 工作开始之前,浏览器需要通过 TCP 与服务器建立连接。也就是说HTTP 的内容是通过 TCP 的传输数据阶段来实现的,你可以结合下图更好地理解这二者的关系。 image.png

HTTP 网络请求的第一步是和服务器建立 TCP 连接。建立 TCP 连接的第一步就是需要 准备 IP 地址 和端口号。是否可以利用 URL 地址来获取 IP 和端口信息呢?

数据包都是通过 IP 地址传输给接收方的。由于 IP 地址是数字标识,比如极客时间网站的 IP 是 39.106.233.176,难以记忆,但使用极客时间的域名 (time.geekbang.org)就好记多了,所以基于这个需求又出现了一个服务,负责把域名和 IP 地址做一一映射关系。这套域名映射为 IP 的系统就叫做“域名系统”,简称 DNS(Domain Name System)。

所以,这样一路推导下来,你会发现在第一步浏览器会请求 DNS 返回域名对应的 IP。当 然浏览器还提供了DNS 数据缓存服务,如果某个域名已经解析过了,那么浏览器会缓存解析的结果,以供下次查询时直接使用,这样也会减少一次网络请求。拿到 IP 之后,接下来就需要获取端口号了。通常情况下,如果 URL 没有特别指明端口号,那么 HTTP 协议默认是 80 端口。

  1. 等待 TCP 队列,端口和 IP 地址都准备好了,那么下一步是不是可以建立 TCP 连接了呢? 依然是“不行”。Chrome 有个机制,同一个域名同时最多只能建立 6 个 TCP 连接, 如果在同一个域名下同时有 10 个请求发生,那么其中 4 个请求会进入排队等待状态,直至进行中的请求完成。如果当前请求数量少于 6,会直接进入下一步,建立 TCP 连接。
  2. 排队等待结束之后,终于可以快乐地和服务器握手了,在 HTTP 工作开始之前,浏览器通过 TCP 与服务器建立连接。
  3. 一旦建立了 TCP 连接,浏览器就可以和服务器进行通信了。而 HTTP 中的数据正是在这个通信过程中传输的。浏览器是如何发送请求信息给服务器的: image.png

服务器端处理 HTTP 请求流程?

  1. 返回请求,curl 来查看返回请求数据,具体使用方法是在命令行中输入以下命令:

    curl -i baidu.com/

注意这里加上了-i是为了返回响应行、响应头和响应体的数据,返回的结果如下图所示,你可以结合这些数据来理解服务器是如何响应浏览器的。 image.png 服务器响应浏览器的具体过程,但并不是所有的请求都可以被服务器处理的,那么一些无法处理或者处理出错的信息,怎么办呢?服务器会通过请求行的状态码来告诉浏览器它的处理结果,比如:404 没有找到页面。

正如浏览器会随同请求发送请求头一样,服务器也会随同响应向浏览器发送响应头。 响应头包含了服务器自身的一些信息,比如服务器生成返回数据的时间、返回的数据类型 (JSON、HTML、流媒体等类型),以及服务器要在客户端保存的 Cookie 等信息。

发送完响应头后,服务器就可以继续发送响应体的数据,通常,响应体就包含了 HTML 的实际内容。

  1. 通常情况下,一旦服务器向客户端返回了请求数据,它就要关闭 TCP 连接。不过如果浏览器或者服务器在其头信息中加入:

    Connection: Keep-Alive

那么 TCP 连接在发送后将仍然保持打开状态,这样浏览器就可以继续通过同一个 TCP 连接 发送请求。保持 TCP 连接可以省去下次请求时需要建立连接的时间,提升资源加载速度。 比如,一个 Web 页面中内嵌的图片就都来自同一个 Web 站点,如果初始化了一个持久连 接,你就可以复用该连接,以请求其他资源,而不需要重新再建立新的 TCP 连接。

  1. 重定向,当你在浏览器中打开 baidu.com 后,你会发现最终打开的页面地址baidu.com这两个 URL 之所以不一样,是因为涉及到了一个重定向操作

    curl -I baidu.com

注意这里输入的参数是-I,和-i不一样,-I表示只需要获取响应头和响应行数据,而不需 要获取响应体的数据。 image.png 从图中你可以看到,响应行返回的状态码是 301,状态 301 就是告诉浏览器,我需要重定 向到另外一个网址,而需要重定向的网址正是包含在响应头的 Location 字段中,接下来, 浏览器获取 Location 字段中的地址,并使用该地址重新导航,这就是一个完整重定向的执行流程。这也就解释了为什么输入的是 baidu.com,最终打开的却是baidu.com 不过也不要认为这种跳转是必然的。如果你打开 12306.cn,你会发现这个站点是 打不开的。这是因为 12306 的服务器并没有处理跳转,所以必须要手动输入完整的 www.12306.com 才能打开页面。

  1. 为什么很多站点第二次打开速度会很快?

原因是第一次加载页面过程中,缓存了一些耗时的数据。DNS 缓存和页面资源缓存这两块数据是会被浏览器缓存的。其中,DNS 缓存比较简单,它主要就是在浏览器本地把对应的 IP 和域名关联起来。重点看下浏览器资源缓存的过程: image.png

2. 登录状态是如何保持的?

image.png 简单地说,如果服务器端发送的响应头内有 Set-Cookie 的字段,那么浏览器就会将该字段的内容保持到本地。当下次客户端再往该服务器发送请求时,客户端会自动在请求头中加入 Cookie 值后再发送出去。服务器端发现客户端发送过来的 Cookie 后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录,最后得到该用户的状态信息。

总结:

image.png

从图中可以看到,浏览器中的 HTTP 请求从发起到结束一共经历了如下八个阶段:构建请求、查找缓存、准备 IP 和端口、等待 TCP 队列、建立 TCP 连接、发起 HTTP 请求、服务器处理请求、服务器返回请求和断开连接。