HTTP/0.9 --- 最早诞生的超文本传输协议
诞生
1991年提出,用来在网络直接传递HTML超文本的内容,被称为 超文本传输协议, 此时要求很简单,就是用来传输体积很小的HTML文件
传输流程
- 根据IP地址,端口和服务器 建立TCP连接,这个过程称为TCP协议的三次握手
- 建立好练级之后,会发送一个 GET请求行 信息,如 GET /index.html 用来获取index.html
- 服务器接受到请求信息之后,读取对应的HTML文件,并将数据以 ASCII字符流 返回给客户端
- HTML文档传输完成后,断开连接
三个特点
- 只有一个请求行,并 没有HTTP请求头和请求体, 因为只需要一个请求行就可以完整表诉客户端需求了
- 服务器也 没有返回头信息,因为服务器并不需要告诉客户端太多数据,只需要返回数据就可以
- 返回的文件是以 ASCII 字符流 传输的,因为都是HTML 格式的文件
HTTP/1.0 --- 被浏览器推动的协议
诞生
1994年,随着拨号上网服务的出现,以及网景浏览器的推出,万维网进入了高速发展阶段。HTTP/0.9 已经不再适用新兴网络的发展,HTTP/1.0就诞生了。
核心诉求
支持多种类型的文件下载(javascript, css , 图片, 音频,视频等不同类型的文件),而且文件类型不仅仅局限于ASCII编码,还有很多其他类型的编码文件
改进
HTTP/1.0 引入了请求投和响应头,在HTTP发送请求的时候会带上请求头信息,服务器返回数据时,会 先 返回响应头信息
具备的功能 -- 依靠请求头和响应头
需要解决的问题:
- 需要知道服务器返回的数据类型,浏览器才能根据不同的类型做针对性的出来
- 为了减轻传输性能,服务器会对数据进行压缩后再传输,所以浏览器需要知道服务器的压缩方法
- 由于需要提供国际化的支持,服务器需要对不同地区提供不同的语言版本,这就需要浏览器告诉服务器想要什么语言的版面
- 浏览器需要知道文件的编码类型
请求头
accept: text/html (期望服务器返回html文件)
accept-encodeding: gzip,deflate,br (期望服务器可以采用gzip,deflate 或者 br 其中一种压缩方式)
accept-language: zh-Cn , zh (期望页面优先语言是中文)
accept-Charset: ISO-8859-1, utf-8 (期望返回的文件编码是UTF-8 或者ISO-8859-1)
响应头
content-encoding: br (服务器值支持br压缩)
content-type: text/html; charset=UTF-8 (服务器返回了html 文件,并且改文件的编码类型是UTF-8)
有了响应头信息,浏览器就会使用br方法来解压文件,再按照UTF-8的编码格式来处理原始文件,最后按照HTML的放肆来解析该文件。这就是HTTP/1.0 支持多文件的一个基本的处理流程。
新增的典型的特性
- 状态码 (服务器告诉浏览器最终处理的结果)
- Cache 机制 (缓存已经下载过的数据)
- 用户代理 (服务器需要统计客户端的基础信息,比如windows和macOS 的用户数量分别是多少)
HTTP/1.1 --- 缝缝补补,快完成使命的协议
添加的功能
1、改进持久链接
HTTP/1.0 每一次HTTP 通信,都需要建立TCP连接, 传输HTTP数据 和 断开TCP连接三个阶段。在当时,由于通信的文件比较小,而且每个页面的引用也不多,所以这种传输形式没什么问题,但是随着浏览器的普及,有时一个页面包含几百个文件,三个步骤无疑会增加大量无谓的开销。 为了解决这个问题 HTTP/1.1z中增加了持久连接的方法,特点是在一个TCP连接上可以传输多个HTTP请求,只要浏览器或者服务器没有明确断开练级金额,那么该TCP连接会一直保持
持久连接在HTTP/1.1中是默认开启的,所以,不需要为了持久连接去HTTP请求头设置信息,如果你不想采用持久连接,可以在HTTP请求头中加上Connection:close。 目前浏览器对于同一个域名,默认允许同时建立6个TCP持久连接
2、不成熟的HTTP管线化(试图解决队头阻塞问题)
持久连接虽然能减少TCP的建立和断开次数,但是他需要等待前面的请求返回之后,才能进行下一次请求,如果TCP通道中的某个请求因为某些原因没有及时返回,就会阻塞后面的所有请求,这就是著名的队头阻塞的问题。(阻塞HTTP请求) HTTP/1.1中试图通过管线化技术来解决队头阻塞问题, 这里的管线化是指江多个HTTP请求整批提交给服务器的技术,虽然可以整批发送请求,不过服务器服务器依然需要根据请求顺序来回复浏览器的请求。
由于各种原因,这门技术被放弃了
3、提供虚拟主机的支持
在HTTP/1.0 中每个域名绑定了一个唯一的IP地址,因此一个服务器只能支持一个域名。但是随着虚拟主机技术的发展,需要实现在一台物理主机上绑定多个虚拟主机,每个虚拟主机都有自己单独的域名,这些单独的域名都公用同一个IP地址。 因此,HTTP/1.1的请求头中增加了Host字段,用来表示当前的域名地址,这样服务器就可以根据不同的 Host 值来做不同的处理。
4、对动态生成的内容提供额完美的支持
HTTP/1.0 时,需要在响应头中设置完整的数据大小,如Content-Length: 901,这样浏览器就可以根据设置的数据大小来接收数据。不过随着服务器端的技术发展,很多页面的内容都是动态生成的,因此在传输数据之前并不知道最终的浏览器大小,这就导致了浏览器不知道何时能接受完所有的文件数据。 HTTP/1.1 通过引入 Chunk transfer 机制,服务器会将数据分割成若干个任意大小的数据块,每个数据块会附上上给数据块的长度,最后使用一个零长度的块作为发送数据完成的标志,这样就提供了对动态内容的支持
5、客户端cookie、安全机制
HTTP/2 --- 提升网络速度
HTTP/1.1 的主要问题
对带宽的利用率不理想(带宽时指每秒最大能发送或者接收的字节数,我们把每秒能发送的最大字节数称为上行带宽,每秒能接收的最大字节数成为下行带宽) 之所以会出现这个问题,由于一下三个原因:
1. TCP的慢启动
一旦一个TCP连接建立之后,就进入了发送数据状态,刚开始TCP协议会采用一个非常慢的速度去发送数据 ,然后加快发送数据的速度,知道把发送数据的速度达到一个理想的状态,我们把这个过程称为慢启动。 慢启动是TCP为了减少网络拥塞的一种策略,我们是没法改变的。
2. 同时开启了多条TCP连接,那么这些连接会竞争固定的带宽
在TCP下载数据过程中,当发现带宽不足的时候,各个TCP连接,就需要动态减慢接收数据的速度,这样就会出现一个问题,因为有点TCP连接下载的时一些关键资源,但是多条TCP连接直接又不能协商让哪些关键资源优先下载,这样就有可能影响那些关键资源的下载速度
3. HTTP/1.1 队头阻塞的问题 (请求会阻塞)
假如有点请求被阻塞了5秒,那么后续排队的请求都要延迟等待5秒,在这个等待过程中,带宽、cpu 都被白白的浪费了。
HTTP/2 的多路复用
HTTP/1.1存在的三个问题中,TCP的慢启动和TCP连接的竞争带宽时由于TCP本身的lin机制导致的,而队头阻塞时由于HTTP/1.1的机制导致的 。
-
虽然TCP有问题,但是我们依然没有换掉TCP的能力,所以我们就要像办法去规避TCP的慢启动和TCP连接之间的竞争问题。 基于此,HTTP/2 的思路,一个域名只使用一个TCP 长连接来传输数据,这样就避免了慢启动和竞争问题。
-
另外对于 请求队头阻塞 的问题,HTTP/2 需要实现资源的并行请求,也就是任何时候都可以将请求发送给服务器,而不需要等待其他请求的完成,然后服务器也可以随时把处理好的请求资源给浏览器
多路复用的实现
HTTP/2 在HTTP协议和TCP协议中间添加了一个二进制分帧层
- 准备好请求数据
- 这些数据经过二进制分帧层处理后,会被转换为一个个带有请求ID编号的帧,通过协议栈将这些帧发送给服务器
- 服务器接收到所有的帧后,会将所有相同的ID的帧合成一条完整的请求信息
- 服务器处理该条请求,并将处理的响应行,响应头,响应体分别发送到二进制分帧层
- 同意,二进制分帧层会将这些响应数据转换为一个个带有请求ID编号的帧,经过协议栈发送给浏览器
- 浏览器接收到帧之后,会根据ID编号,将帧的数据交给对应的请求
HTTP/2.0 的其他特性
- 可以设置请求的优先级(发送请求时可以标上该请求的优先级)
- 服务器推送 (HTTP/2 可以将数据提前推送到浏览器,)
- 头部压缩
HTTP/3 --- 甩掉TCP、TLS包袱
HTTP/2 的缺陷
- TCP的队头阻塞
虽然HTTP/2 解决了应用层面的队头阻塞问题(HTTP 请求的阻塞),不过和HTTP/1.1一样,HTTP/2 依然时基于TCP协议的,而TCP最初就时为了单连接而设计的,把TCP连接看出时两台计算机之间的一个虚拟管道,计算机一端要传输的数据按顺序放入管道,最终数据会议相同的顺序出现在管道一头。如果在数据传输过程中,有一个数据丢包,那么整个TCP的连接就处于暂停状态,需要等待丢失的数据包被重新传输过来。
在TCP 传输过程中,由于单个数据包丢失而造成的阻塞称为TCP上的队头阻塞(阻塞数据包)
- TCP 建立连接的延时
我们知道HTTP/1 和 HTTP/2 都是使用TCP协议来传输的,如果时使用HTTPS,还需要是哦那个TLS协议进行安全传输,而使用TLS也需要一个握手过程,这样就需要两个握手延迟过程
- 建立TCP链接的三次握手需要 1.5个RTT (Round Trip Time ,从浏览器发送一个数据到服务器再次从服务器返回数据包到浏览器的整个往返时间,也是衡量网络性能的指标)
- TLS 大致需要1~2个RTT
总之,在传输数据之前需要花掉3~4个RTT。如果浏览器和服务器的物理距离比较近,那么一个RTT的时间可能在10毫秒以内,也就是总共要消耗掉30~40毫秒,还可以接收, 如果服务器相隔较远, 一个RTT 就可能需要100 毫秒一些了,这种情况下,整个握手过程需要 300~400毫秒,就很慢了。
- TCP 协议僵化
我们知道了TCP协议存在队头阻塞和建立连接延迟等缺点,是否可以通过改进TCP协议解决这些问题?难
QUIC协议
基于UDP实现了类似于TCP的多路数据流,传输可靠性等功能,我们把这套功能称为QUIC协议
实现的功能:
- 实现了类似TCP的流量控制/传输可靠性的功能
- 继承了TLS 加密功能
- 实现了HTTP/2 中的多路复用功能
- 实现了快速握手功能
HTTP/3的挑战
- 服务器和浏览器端都没有对HTTP/3 提供比较完整的支持
- 部署存在问题,因为系统内核对UDP的优化远远没有达到TCP的优化成都,这也是阻碍QUIC的一个重要原因
- 中间设备僵化,这些设备对UDP的优化程度远远低于TCP