HTTP/0.9 完整请求流程
- 客户端根据 IP 地址、端口、服务器建立 TCP 连接(三次握手)
- 发送一个请求行信息来获取内容,如:GET /index.html
- 服务器接收到信息,读取对应的 index.html, 将数据以 ASCLL 字符流返回给客户端
- 传输完成后,断开连接
三个特点
- 只有请求行,无请求头和请求体
- 服务器只返回数据,没有返回头之类的信息
- 返回内容是以 ASCLL 字符流形式返回
HTTP/1.0
此时浏览器不仅支持 HTML,还支持 JS、CSS、图片、音频等不同类型文件。
- 如何实现多类型文件的下载?
要想下载这些不同类型的文件,就需要告诉服务器需要文件的类型、编码等信息。于是 HTTP/1.0 就加入了请求头和响应头。发送请求时,带上请求头信息,返回数据时,会先返回响应头信息。 - HTTP/1.0 请求头各个字段的来源
accept: text/html: 浏览器需要知道服务器返回什么类型的数据,然后才能针对不同类型的数据做处理。此处表示期望服务器返回 html 类型的文件。
accept-encoding: gzip,deflate,br: 由于万维网支持的数据越来越广,单个文件的数据量也变得越来越大。为了减轻传输性能,服务器汇兑数据压缩后再传输,所以浏览器需要知道服务器的压缩方法以便解密用。此处表示浏览器期望服务器可以采用 gzip、deflate、br 这几种压缩方法。
accept-charest: ISO-8859-1,UTF-8: 各种不同类型的文件所用的编码方式都不太一样,为了准确读取文件,浏览器也需要知道文件的编码类型。此处表示期望返回的文件编码为 UTF-8 或 ISO-8859-1。
accept-language: zh-CN,zh: 提供国际化支持,对不同地区提供不同的语言版本 。此处表示期望优先返回的语言是中文。 - HTTP/1.0 响应头的数据信息
conte nt-encoding: br:告诉浏览器,服务器采用了 br 的压缩方法
content-type: text/html; charset=UTF-8:告诉浏览器,服务器返回的是 html 文件并且采用 UTF-8 编码。 - 状态码
有的请求服务器可能无法处理或者处理出错,这时就要告诉浏览器最终处理该请求的情况,就引入了状态码,通过响应行的方式来通知浏览器。 - Cache 机制
为了减轻服务器的压力,用来缓存已经下载过的数据。 - user-agent
服务器需要统计客户端的基础信息,比如:windows、mac、android 的用户数量分别是多少。
HTTP1.1 改进的功能
改进持久连接
随着浏览器普及,单个页面中的资源文件越来越多,如果每个文件的下载都要建立 TCP 连接、传输数据、断开连接的步骤,会增加大量不必要的开销。
为了解决上述问题,HTTP1.1 增加了持久连接,在一个 TCP 连接上可传输多个 HTTP 请求,只要浏览器和服务器没有明确断开连接,这个 TCP 连接会一直保持。
持久连接在 HTTP1.1 中是默认开启的。若不想采用,可以在请求头中加上Connection: close
不成熟的 HTTP 管线化
持久连接虽然能减少 TCP 的建立和断开次数,但需要等待前面每次请求返回之后,才能进行下一次请求。如果某个请求没有及时返回,那么会阻塞后面的所有请求,这就是队头阻塞问题。
HTTP1.1 试图通过管线化,将多个 HTTP 请求批量提交给服务器,不过服务器依然要根据请求顺序来回复浏览器的请求。
Host 字段:提供虚拟主机的支持
HTTP1.0 中,每个域名只能绑定一个 IP 地址,即一个服务器只能支持一个域名。随着虚拟主机技术的发展,一个物理主机上可以绑定多个虚拟主机,每个虚拟主机都有自己单独的域名,这些域名公用同一个 IP 地址。
因此,HTTP1.1 的请求头中增加 Host 字段,用来表示当前的域名地址,这样服务器就可以根据不同 Host 做不同处理。
对动态内容提供了完美支持
HTTP1.0 需要通过响应头 content-length 告诉浏览器数据的大小,这样浏览器就可以根据设置的数据大小来接收数据(浏览器对大文件不能一次性接受,所以要根据数据大小来判断是否接受完毕)。
但现在服务端返回的都是动态生成的内容,因此在传输数据之前并不知道最终数据的大小,进而导致浏览器不知道何时会接受完所有数据。
HTTP1.1 引入 Chunk transfer 机制,在服务器端将数据分割成若干个任意大小的数据块,在发送时附上数据块的长度,最后使用 0 长度的数据块表示发送完毕,这样就支持动态内容。
客户端的 Cookie、安全机制
Cookie 机制:服务器发送的响应中若有 set-cookie 字段,浏览器就会将字段内容保存到本地,下次再请求时就会把 cookie 带上。可用来存储用户的登录信息。
安全机制:……
HTTP1.1 核心优化方式:
- 增加持久连接
- 每个域名可同时维护 6 个 TCP 持久连接
- 使用 CDN 来实现域名分片机制
通过这些方式大大提高了页面的下载速度。
如果使用单个 TCP 持久连接,下载 100 个资源用时:100×n×RTT(Round-Trip TIme 往返时延)。
通过上面技术用时为:100×n×RTT/(6×CDN)
HTTP1.1 主要问题
对带宽的利用率不理想。
带宽:每秒最大能发送或者接收的字节数。
上行带宽:每秒能发送的最大字节数。
下行带宽:每秒能接受的最大字节数。
100M 带宽,实际下载速度能达到 12.5M/s。
下载速度的 M 单位是”字节“。
带宽的 M 是 单位是”位“。
1 字节 = 8 位
加载页面很难将 12.5M 全部用满,主要有下面 3 个原因。
- TCP 慢启动
一个 TCP 建立连接之后,就进入发送数据状态。刚开始 TCP 协议会采用一个非常慢的速度去发送数据,然后慢慢加快速度
之所以慢启动会带来性能问题,是因为页面中关键资源 html,css,js 加载的时间可能比慢启动耗费的时间还少,这样就推迟了首屏渲染时间了。
慢启动是 TCP 为减少网络拥赛的策略,没有办法改变。 同时开启多条 TCP 连接,这些连接会竞争固定的带宽。
同时建立多条 TCP 连接,当带宽不足时,这些 TCP 连接会减慢发送或者接收的速度。
比如:一个页面 200 个资源,用了 3 个 CDN,即 18 个 TCP 连接来下载资源。当带宽不足时,各个 TCP 连接就需要动态减慢接收数据的速度。
有的 TCP 连接下载的是关键资源(html,css,js等),有的下载的则是普通资源(图片、视频),多条 TCP 之间不能协商让关键资源优先下载,这样就会影响关键资源的下载速度。HTTP1.1 队头阻塞问题。
使用持久连接时,多个请求共用一个 TCP 连接,当一个请求被阻塞了 5s,后面排队的请求都要延迟等待 5s,这个过程中带宽,CPU 都被白白浪费了。
浏览器生成页面过程中,提前接受到数据就可以做预处理操作。比如:提前接收到图片就可以开始编码操作,等到用时便可直接给出处理后的数据,让用户感到整体速度提升。
队头阻塞使得这些数据不能并行请求,不利于浏览器优化。
