目录
- 1. HTTP版本
- 1.1 HTTP 1.0
- 1.2 HTTP 1.1
- 1.3 HTTP 2.0
- 2. HTTP缓存
- 2.1 缓存的简介
- 1. 强缓存
- 2. 协商缓存
- 3. 两者异同
- 2.2 缓存的优点
1. HTTP版本
1.1 HTTP 1.0
HTTP 1.0版本较之前的0.9版本增加了以下功能:
- 该版本的HTTP协议可以发送任何格式的内容
- 除了GET命令,该版本还引入了POST命令,丰富了浏览器与服务器的互动手段
- HTTP请求和回应的格式发生了改变,除了数据部分,每次通信还必须包括头部信息,头部信息用来描述一些元数据
- 其次还增加了状态码、多字符集支持、多部分发送、权限、缓存、内部编码等功能
该版本的主要缺点:
- 每个TCP连接都只能发送一次请求,发送完数据,连接就必须要关闭,如果想要继续请求,就要重新建立TCP连接,而TCP连接的三次握手的速度较慢,这就使得HTTP请求的性能较差。
1.2 HTTP 1.1
HTTP 1.1版本较之前的1.0版本又有了更大的更新,它进一步完善了HTTP协议,现在仍然有在使用,它主要有以下更新:
- 持久连接(长连接)
该版本之前的版本所建立的都是短连接,该版本引入了持久连接的概念,就是TCP连接默认是不关闭的,建立一个TCP连接,就可以发送多个请求,减少了建立和关闭连接的消耗和延迟
在请求头设置一个非标准的Connection字段:Connection: keep-alive
就可以进行长连接,这个字段要求服务器不要关闭TCP连接,服务器同样会回应这个字段。如果想要关闭TCP连接,就要在请求中设置字段:Connection: false
- 管道机制:该版本还引入了管道机制,即在一个TCP连接里,客户端可以同时发送多个请求,不需要等收到上一个请求回应,就可以发送新的请求,但是请求的响应还是按照请求发送的顺序返回的,这样就进一步提高了HTTP协议的效率
- 分块传输编码:在HTTP1.0版本中,如果在服务器端遇到较为耗费时间的操作,那么需要等到这一操作全部完成后,才会向客户端发送数据,这段等待时间很影响性能和客户体验。多以使用分块传输编码,只要请求或者回应的头部信息有
Transfer-Encoding
字段:Transfer-Encoding: chunked
,就表明回应将由数量未定的数据块组成。每个非空的数据块之前,会有一个16进制的数值,表示这个块的长度。最后是一个大小为0的块,就表示本次回应的数据发送完了
示例:
HTTP/1.1 200 OKContent-Type: text/plainTransfer-Encoding: chunked
25
This is the data in the first chunk
1C
and this is the second one
3
con
8
sequence
0
- 加入了几个请求方法:PUT、PATCH、HEAD、 OPTIONS、DELETE
- 加入了缓存机制:强缓存和协商缓存(下文会介绍)
- 客户端请求的头部信息加入了
Host
字段,用来指定服务器的域名,这样就可以区分同一个物理主机中的不同虚拟主机的域名
虽然HTTP 1.1对HTTP协议进行了完善,但是还是存在一些问题:
- 虽然可以同时发送多个请求,但是服务器处理请求是按照顺序依次处理的,如果前面处理的慢,后面的额就会有很多请求排队,这就造成了队头堵塞
- 管道机制默认是关闭状态
1.3 HTTP 2.0
首先理解一下以下概念:
(1)流(stream):已建立连接上的双向字节流。
(2)消息:与逻辑消息对应的完整的一系列数据帧。
(3)帧(frame):HTTP2.0通信的最小单位,每个帧包含帧头部,至少也会标识出当前帧所属的流(stream id)。
HTTP 2.0 版本有以下更新:
- 多路复用:在一个TCP连接上,可以发送个多个HTTP请求,服务端则可以通过帧中的表示知道该帧属于哪个流,通过重新排序还原请求。多路复用允许并发的发起多个请求,每个请求及该请求的响应不需要等待其他的请求和响应,避免了队头堵塞。
- 二进制分帧:在应用层和传输层之间增加了一个二进制的分帧层,解决了HTTP1.1 的性能限制,改进了传输性能,实现了低延迟和高吞吐量。在二进制分帧层中,HTTP2.0将所传输的信息分割成更小的信息和帧,并对他们进行二进制格式的编码,将首部信息被封装到
HEADER frame
,而相应的Request Body
则封装到DATA frame
里面。简单来说就是把原来HTTP1.x的header
和body
部分用frame
重新封装了一层。 - 头部压缩:在HTTP 1.x中请求头部数据时以纯数字形式发送的,这就给请求带来了负荷,HTTP 2.0使用
encoder
来减少需要传输的头部大小,通讯双方各自cache
一份头部fields
表,既避免了重复头部的传输,又减小了需要传输的大小,从而降低延迟。 - 服务器推送:服务器可以主动向客户端推送资源,服务器推送的资源可以进行缓存,当再次请求时,可以在缓存中请求到。
2. HTTP缓存
上文中提到了HTTP1.1版本加入了缓存机制,下面就对HTTP的缓存进行简单介绍。
HTTP缓存顾名思义就是将已获取的资源进行存储,以便重用,进而提高应用的性能。缓存发生在客户端,主要分为两种:强缓存和协商缓存。
2.1 缓存的简介
1. 强缓存
强缓存是指向浏览器缓存查找该请求的结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程。强缓存可以理解为无需验证的缓存策略,它的响应头部有两个字段:Expires
和Cache-Control
来表明规则。
(1)Expires:
Expires
是指缓存过期的时间,超过这个时间,资源就会过期,即在此发起该请求,如果客户端的时间小于Expires
的值,直接使用缓存的结果。
该字段是HTTP1.0中的标准,所以更倾向于使用Cache-Control
,如果两个同时存在,Cache-Control
优先级会更高。
(2)Cache-Control
Cache-Control
是HTTP1.1中重要的规则,主要用于网页的缓存,它可以在请求头和响应头中使用,常见的属性值有:
-
max-age
:单位是秒,缓存时间计算的方式是距离发起的时间的秒数,超过间隔的秒数缓存失效 -
no-cache
:不使用强缓存,需要与服务器验证缓存是否新鲜 -
no-store
:禁止使用缓存(包括协商缓存),每次都向服务器请求最新的资源 -
private
:所有内容只有客户端可以缓存,Cache-Control的默认取值 -
public
:所有内容都将被缓存(客户端和代理服务器都可缓存) -
must-revalidate
:在缓存过期前可以使用,过期后必须向服务器验证
判断缓存是否失效:
2. 协商缓存
协商缓存需要进行对比判断是否可以使用缓存。浏览器第一次请求数据时,服务器会将缓存标识与数据一起响应给客户端,客户端将它们备份至缓存中。再次请求时,客户端会将缓存中的标识发送给服务器,服务器根据此标识判断。若未失效,返回304状态码,浏览器拿到此状态码就可以直接使用缓存数据了。
协商缓存的标识是在响应报文的HTTP头部,和请求结果一起返回给客户端,它有两个字段,分别是:Last-Modified / If-Modified-Since
和 Etag / If-None-Match
,后者优先级较高。
-
Last-Modified
: 是服务器响应请求时,返回该资源文件在服务器最后被修改的时间,需要保证服务器时间准确(适合不重要、量大的资源) -
if-Modified-Since
:浏览器再次请求服务器的时候,请求头会包含此字段,后面跟着在缓存中获得的最后修改时间。服务端收到此请求头发现有if-Modified-Since,则与被请求资源的最后修改时间进行对比,如果一致则返回304和响应报文头,浏览器只需要从缓存中获取信息即可。
(1)如果没有被修改:则开始`继续’传送文件: 服务器返回: 200 OK
(2)如果文件被修改:则不传输,服务器返回: 412 Precondition failed (预处理错误) -
Etag
:服务器响应请求时,通过此字段告诉浏览器当前资源在服务器生成的唯一标识,生成规则由服务器决定(适合重要、量小的资源) -
If-None-Match
:再次请求服务器时,浏览器的请求报文头部会包含此字段,后面的值为在缓存中获取的标识。服务器接收到次报文后发现If-None-Match则与被请求资源的唯一标识进行对比。
(1)不同,说明资源被改动过,则响应整个资源内容,返回状态码200。
(2)相同,说明资源没有修改,则响应header,浏览器直接从缓存中获取数据信息。返回状态码304.
3. 两者异同
- 两者的共同点是:如果命中,都是从客户端缓存中加载资源,而不是从服务器加载资源数据
- 两者的区别是:强缓存不发请求到服务器,协商缓存会发请求到服务器
2.2 缓存的优点
- 减少了冗余的数据传递,节省宽带流量
- 减少了服务器的负担,大大提高了网站性能
- 加快了客户端加载网页的速度 这也正是HTTP缓存属于客户端缓存的原因。