HTTP1.0时代
HTTP/0.9——HTML文件
作用:传输体积很小的HTML文件
基于请求响应的模式
格式
请求:
GET /index.html
(因为只需要一个请求行就可以完整表达客户端的需求了)
响应:只有响应体
(没有响应头,服务器端并不需要告诉客户端太多信息, 只需要返回数据就可以了)
编码
因为都是HTML文件,所以ASCII字节码最合适
HTTP/1.0——多种文件类型
流程
-
发起请求:浏览器用HTTP请求头告诉服务器它期待什么文件类型、文件编码、压缩形式、文件语言。
-
处理请求:根据请求头的信息来准备响应,不过有时候会有一些意外情况发生,如浏览器请求是gzip,但是服务器只支持br压缩,通过响应头中的 content- encoding字段告诉浏览器最终的处理结果
-
接收响应 >>浏览器就会使用br方法来解压文件,再按照UTF-8的编码格式来解码,最后按照HTML的方式来解析该文件。
格式
请求
GET /4848 HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/3.01 (X11; I; SunOS 5.4 sun4m)
Pragma: no-cache
Host: tecfa.unige.ch:7778
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
复制代码
响应
HTTP/1.0 200 ok
Date: Wed, 16 Apr 97 22:54:42 GMT
Server: E_WEB (E_MOO-Web-Server/1.2d - Not WOO) (LambdaMOO 1.8.0p5)
Content-type: text/html
<title>Query results</title>
<h1>Query results</h1>
......
复制代码
作用——请求头/响应行+响应头实现
- 报告服务器的最终处理情况——通过响应行的状态码
HTTP/1.0 200 OK
复制代码
-
支持多种文件类型
HTML/ Javascript/CSS/图片/音频/视频
需要知道服务器返回的数据是什么类型的,然后浏览器才能根据不同的数据类型做针对性的处理
accept: application/json, text/plain, */*
content-type: application/json
复制代码
-
支持文件压缩
通常是CSS/JS文件
为了减轻传输性能,服务器会对数据进行压缩后再传输,所以浏览器需要知道服务器压缩的方法
accept-encoding: gzip, deflate, br
content-encoding: gzip
复制代码
- 支持多种语言
accept-language: zh-CN,zh
复制代码
-
支持多种编码
由于增加了各种不同类型的文件,而每种文件的编码形式又可能不一样,为了能够准确地读取文件,浏览器需要知道文件的编码类型,不只ASCII编码
accept:text/plain; charset=utf-8
content-type: application/json; charset=utf-8
复制代码
-
为了减轻服务器的压力
提供了Cache机制,用来缓存已经下载过的数据
cache-control: no-store, no-cache, must-revalidate
复制代码
-
可统计客户端的基础信息
请求头中的用户代理
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)
复制代码
HTTP/1.1——TCP持久连接
TCP持久链接
在一个TCP连接上可以传输多个HTTP请求,只要浏览器或者服务器没有明确断开连接,那么该TCP连接会一直保持。减少TCP建立连接和断开连接的次数,减少了服务器的负担,缩短整体请求时长
而HTTP/1.0每进行一次HTTP通信,都需要经历建立TCP连接、传輸HTP数据和断开TCP连接三个阶段
如果文件比较小,而且每个页面的引用也不多,这种传输形式没什么大问题。单个页面中的图片文件越来越多,有时候一个页面可能包含了几百个外部引用的资源文件,如果在下载每个文件的时候,都需要经历建立TCP连接、传输数据和断开连接这样的步骤,无疑会増加大量无谓的开销
HTTP/1.0的通信模式
HTTP/1.1长连接
单个域名最大持久连接
浏览器中对同一个域名允许同时建立最多6个TCP持久连接
关闭持久链接
Connection: close
复制代码
持久连接在HTTP/1.1中是默认开启的(Connection: keep-alive )不需要专门设置请求头信息
支持虚拟主机
Host: fastlane.rubiconproject.com
复制代码
HTTP/11的请求头中增加了Host字段,用来表示当前的域名地址,这样服务器就可以根据不同的Host值做不同的处理
在HTTP/1.0中,一个IP只能服务于一个域名
但是随着虚拟主机技术的发展,需要实现在一台物理主机上绑定多个虚拟主机
每个虚拟主机都有自己的单独的域名,这些单独的域名都公用同一个P地址。
尝试管线化
HTTP/1.1中试图通过管线化(将多个HTTP整批发送, 但服务器依然需要根据请求顺序来回复))的技术来解決队头阻塞(一个HTTP请求收到响应才能发送下一个请求)的问题
FireFox、 Chrome都做过管线化的试验,但是由于各种原因,它们最终都放弃了管线化技术
支持动态生成内容
通常是CSS/JS文件
支持动态生成内容
Transfer-Encodeing: chunked
复制代码
响应头中应设置完整的数据大小(Content-Length: 901)这样浏览器就可以根据设置的数据大小来接收数据。不过随着服务器端的技术发展,很多页面的内容都是动态生成的,因此在传输数据之前并不知道最终的数据大小,这就导致了浏览器不知道何时会接收完所有的文件数据。
HTTP/11通过引入Chunktransfer机制来解決这个问题,服务器会将数据分割成若干个任意大小的数据块,每个数据块发送时会附上上个数据块的长度,最后使用一个零长度的块作为发送数据完成的标志。这样就提供了对动态内容的支持。
客户端 Cookie、安全机制
HTTP/2.0时代
没有了请求行和响应行
HTTP/1.1时代
-
特点:TCP持久连接;每个域名最多有6个TCP持久连接;域名分片机制
比起单个TCP的持久连接,时间只要1/6*CDN不足:带宽利用率很低帯宽
-
带宽无法充分利用
HTTP/1.1的一个核心问题——很难将带宽用满。比如我们常说的100M带宽,实际的下载速度能达到12.5M/S,而采用HTTP/1.1时,也许在加载页面资源时最大只能使用到2.5M/S,很难将12.5M全部用满帯宽:是指每秒最大能发送或者接收的字节数。我们把每秒能发送的最大字节数称为上行带宽,每秒能够接收的最大字节数称为下行带宽HTTP/1.1时代
原因
- TCP的慢启动
- 多条TCP连接,竞争固定的带宽
- HTTP/1.1队头阻塞的问题
慢启动和多个TCP相互竞争带宽是由于TCP本身的机制导致的,我们没有换掉TCP的能力,所以我们就要想办法去解决HTTP队头阻塞
TCP慢启动: 旦一个TCP连接建立之后,就进入了发送数据状态,刚开始TCP协议会采用一个非常慢的速度去发送数据,然后慢慢加快发送数据的速度,直到发送数据的速度达到一个理想状态,我们把这个过程称为慢启动
HTTP队头阻塞: 当前的请求收到响应后,才能处理其他的请求只,使得数据不能并行请求
多路复用——HTTP/2解决HTTP队头阻塞
一个域名只使用一个TCP连接,这样整个页面只需要一次慢启动,同时也避免了多个TCP连接竟争
每个请求都有一个对应的ID(如 stream1表示 index.html的请求, stream2表示fo.css 的请求。这样在浏览器端,就可以随时将请求发送给服务器了)HTTP队头阻塞
实现——二进制分帧
-
发送方:发送的信息经过二进制分帧层处理之后,会被转換为一个个带有请求编号的帧
-
接收方:接收到所有帧之后,会将所有相同的帧合并为一条完整的信息
可以设置请求的优先级
多路复用技术把请求分成一帧一帧的传输,带来的额外好处当收到一个优先级高的请求时,可以暂停之前的,优先处理关键资源(JS/CSS)
比如服务器可能早就缓存好了 index. htm和 bar. js的响应头信息,那么当接收到请求的时候就可以立即把 index. html和 bar. js p的响应头信息返回给浏览器,然后再将 index. html和 bar. js 的响应体数据返回给浏览器
服务器推送
对首次打开页面的速度起到了至关重要的作用。当用户请求ー个HTML页面之后,服务器知道该HTML页面会引用几个重要的 Javascript文件和CSS文件,那么在接收到HTML请求之后,附帯将要使用的CSS文件和 Javascript文件一并发送给浏览器,这样当浏览器解析完HTML文件之后,就能直接拿到需要的CSS文件和 Javascript文件,
头部压缩
通过HPACK算法实现,即字典+哈夫曼编码
HTTP/3.0时代
HTTP/2.0时代
虽然HTP/2解決了应用层面的队头阻塞问题,但依旧存在TCP的队头阻塞和TCP握手时间过长
- 队头阻塞
http的队头阻塞:一个HTTP请求收到响应才能发送下一个请求
在HTTP/2.0的时代解决了HTTP队头i阻塞。通过二进制分帧frame将不同请求共用一个tcp连接, 即多路复用的底层实现
在HTTP/1.1时代尝试通过管线化技术解决(请求可以并行发出,但是响应必须串行返回, 后一个响应必须在前一个响应之后.原因是:没有序号标明顺序,只能串行接收)
请求必须是幂等请求,不能修改资源。因为,意外中断时候,客户端需要把未收到响应的请求重发,非幂等请求,会造成资源破坏,所以浏览器放弃了这种优化.转而使用增加TCP连接数(同一个域名6个)和域名分片技术TCP的队头阻塞:TCP数据包是有序传输,中间一个数据包丢失,会等待该数据包重传,造成后面的数据包的阻塞。
TCP的队头阻塞: TCP数据包是有序传输,中间一个数据包丢失,会等待该数据包重传,造成后面的数据包的阻塞。
二进制分帧的TCP服务于一个请求时:
浏览器为每个域名开启了6个TCP连接,如果其中的1 个TCP连接发生了队头阻塞,那么其他的5个连接依然可以继续传输数据。
二进制分帧的TCP服务于多个请求时
其中任意一路数据流中出现了丢包的情况,那么就会阻塞该TCP连接中的所有请求
在TCP传输过程中,由于单个数据包的丢失而造成的阻塞称为TCP上的队头阻塞
随着丟包率的增加,HTTP/2的传输效率也会越来越差。有测试数据表明,当系统达到了2%的丢包率时,HTTP/1的传输效率反而比HTTP/2表现得更好
- TCP握手时间过长
在建立TCP连接的时候,需要和服务器进行三次握手来确认连接成功,也就是说需要在消耗完1.5个RTT之后才能进行数据传输。
如果使用HTTPS的话,还需要TLS握手过程,这样就需要有两个握手延迟过程。进行TLS连接,TLS有两个版本一TLS12和TLS1.3,每个版本建立连接所花的时间不同,大致是需要
在传输数据之前,我们需要花掉3~4个RTT
网络延迟RTT(Round Trip Time)
从浏览器发送一个数据包到服务器,再从服务器返回数据包到浏览器的整个往返时间称为RTTTCP握手时间过长
现在我们知道了TCP协议存在队头阻塞和建立连接延迟等缺点,但TCP协议已经僵化(中间设备的僵化—+操作系统也是导致TCP协议僵化),只能靠使用UDP协议进一步优化
基于QUIC协议——可靠+复用+加密传输
- 类似TCP的流量控制、传输可靠性的功能
- 集成了TLS加密功能
- 实现了快速握手功能
- 实现了HTTP/2中的多路复用功能
QUIC集成了“TCP可靠+多路复用+加密传输功能”从协议最底层对Web的文件传输做了比较彻底的优化,所以等生态相对成熟时,可以用来打造比现在的HTTP/2还更加高效的网络
HTTP/3的挑战
第一:从目前的情况来看,服务器和浏览器端都没有对HTTP/3提供比较完整的支持。
Chrome虽然在数年前就开始支持Gooe版本的oUC,但是这个版本的QUIC和官方的QUC存在着非常大的差异第二:部署HTTP/3也存在着非常大的问题。因为系統内核对UDP的优化远远没有达到TCP的优化程度,这也是阻碍QUIC的一个重要原因第三:中间设备僵化的问题。这些设备对UDP的优化程度远远低于TCP,据统计使用QUC协议时,大约有3%~7%的丢包率