• HTTP1.0
      • 浏览器与服务器仅支持短连接每发送一个请求会进行一次TCP连接(三次握手、四次挥手)
      • 出现对头阻塞问题head of line blocking规定下一个请求必须在前一个请求响应到达之前才能发送。假设前一个请求响应一直不到达,那么下一个请求就不发送,同样的后面的请求也给阻塞了
    • HTTP1.1
      • 支持持久连接(长连接)在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟一个包含有许多图像的网页文件的多个请求和应答可以在一个连接中传输,但每个单独的网页文件的请求和应答仍然需要使用各自的连接
        • 请求头部Connection: Keep-Alive/false
      • 支持请求管道化pipelining管线化使得请求能够“并行”传输服务器必须按照客户端请求的先后顺序依次回送相应的结果,以保证客户端能够区分出每次请求的响应内容。(先进先出队列)客户端同时发了两个请求分别来获取html和css,假如说服务器的css资源先准备就绪,服务器也会先发送html再发送css。换句话来说,只有等到html响应的资源完全传输完毕后,css响应的资源才能开始传输。也就是说,不允许同时存在两个并行的响应
        • 无法解决队头阻塞(head of line blocking)的问题,“管道化”技术存在各种各样的问题,它的开启条件很苛刻,很多浏览器不支持或直接关闭网络延迟问题
      • 支持缓存处理浏览器发送一次请求的流程如下:浏览器先根据这个资源的http头信息来判断是否命中强缓存。如果命中则直接加在缓存中的资源,并不会将请求发送到服务器。如果未命中强缓存,则浏览器会将资源加载请求发送到服务器。服务器来判断浏览器本地缓存是否失效。若可以使用,则服务器并不会返回资源信息,浏览器继续从缓存加载资源。如果未命中协商缓存,则服务器会将完整的资源返回给浏览器,浏览器加载新资源,并更新缓存。
        • 本地缓存在用户第一次访问一个资源文件时,浏览器会将符合条件的资源文件添加到缓存池中。在用户通过浏览器访问一个资源文件时,浏览器会先从本地缓存池中检索有无该文件的缓存,符合命中条件则直接使用该缓存资源,如缓存池中没有该文件,则会去服务器上请求该文件。
          • Expires 或 Cache-ControlExpires: Fri, 05 Jul 2002, 05:00:00 GTM // 一个绝对日期,浏览器判断文件是否过期时,对比的是用户机器上的时间而不是服务器上的时间——用户本地时间是会影响到原先的缓存意图的Cache-Control: max-age=484200 // 接受一个秒数作为文档的生存时间。这个时间是一个相对时间,一个倒计时的秒数,不依赖于机器时间如果同时使用 Expires 和 Cache-Control 首部,那么浏览器将以优先值更高的 Cache-Control 为准
        • 协商缓存当本地缓存文件到达缓存期限时,如果此时用户再次发起请求,浏览器将会给原始服务器发出一个 HTTP 请求,假使服务器的文件并没有进行过任何更新,这时缓存虽然是过期的但实际上仍是有效的。对于这种情况,如果服务器这时直接重发一份相同的文件,那么就可能造成浪费。针对此,HTTP 也制定了一些策略来进行优化,我们将这个阶段成为协商缓存或再验证
          当缓存未命中时,浏览器需要对它们缓存的副本进行新鲜度检测,看看它们是否仍是服务器上最新的版本。为了有效地进行再验证,HTTP 定义了一些特殊的请求,不用从服务器上获取整个对象,就可以较快地检测出内容是否是最新的。我们将这些请求称为“条件 GET”请求。当服务器的资源未发生更新时,服务器会返回304 Not Modified响应,不会返回文档的主体,这样一来,网络请求效率就会比普通 GET 请求高一点。当服务器的资源发生更新时,服务器会返回200响应,并在报文体中携带新的文件内容,这种情况下,与普通 GET 请求获取资源效率无异。
          • 条件请求首部If-Modified-Since、If-None-Match、If-Unmodified-Since、If-Range、If-Match
            首部 描述If-Modified-Since:< date >如果从指定日期之后文档被修改过了,就执行请求的方法获取新的内容。与服务器响应首部 Last-Modified 配合使用。If-None-Match:< tag > 服务器可以为文档提供特殊的标签(ETag),而不是将其与最近修改日期相匹配,这些标签就像序列号一样。如果已缓存标签与服务器文档中的标签有所不同,If-None-Match 首部就会执行请求的方法,获取新的内容。与服务器响应首部 ETag 配合使用。If-Unmodified-Since 在进行部分文件的传输时,获取文件的其余部分之前要确保文件未发生变化,此时这个首部是非常有用的。If-Range 支持对不完整文档的缓存。用于判断实体是否发生改变,如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体If-Match 用于与 Web 服务器打交道时的并发控制
            • if-None-Match: ETag有些情况下只使用最后修改日期来进行再验证是不够的。有些文档可能会被周期性地重写,但实际包含的数据常常是一样的。尽管内容没有变化,但修改日期会发生变化。有些文档被修改了,但所做的修改并不重要,比如对拼写或注释的修改。有些服务器提供的文档会在亚秒间隙发生变化,比如实时监视器,对这些服务器来说,以一秒为粒度的修改日期可能就不够用了。
        • 应用层缓存(LocalStorage、SessionStorage、Cookie)
          • LocalStorage大小:一般为 5MB生命期:除非被清除,否则永久保存易用性:高,源生接口容易使用仅在客户端(即浏览器)中保存,不参与和服务器的通信
          • SessionStorage大小:一般为 5MB生命期:仅在当前会话下有效,关闭页面或浏览器后被清除易用性:高,源生接口容易使用仅在客户端(即浏览器)中保存,不参与和服务器的通信
          • Cookie大小:一般为 4KB生命期:一般由服务器生成,可设置失效时间。如果在浏览器端生成 Cookie,默认是关闭浏览器后失效易用性:差,需要程序员自己封装,源生的Cookie接口不友好每次请求会默认携带在HTTP头中,如果使用 cookie 保存过多数据会降低 HTTP 利用率
      • 支持断点传输/分块传输HTTP1.1 协议开始支持获取文件的部分内容,这为并行下载以及断点续传提供了技术支持。
        • Range(客户端)格式:Range:(unit=first byte pos)-[last byte pos]Range: bytes=0-499 表示第 0-499 字节范围的内容Range: bytes=500-999 表示第 500-999 字节范围的内容Range: bytes=-500 表示最后 500 字节的内容Range: bytes=500- 表示从第 500 字节开始到文件结束部分的内容Range: bytes=0-0,-1 表示第一个和最后一个字节Range: bytes=500-600,601-999 同时指定几个范围
        • Content-Range(服务端)格式:Content-Range: bytes (unit first byte pos) - [last byte pos]/[entity legth]Content-Range: bytes 0-499/22400 //0-499 是指当前发送的数据的范围,而 22400 则是文件的总大小。需要有一个标识文件唯一性的方法,方法与本文协商缓存判断文件是否改变的方法一样
        • Chunked transfer-coding发送方将消息分割成若干个任意大小的数据块,每个数据块在发送时都会附上块的长度,最后用一个零长度的块作为消息结束的标志。这种方法允许发送方只缓冲消息的一个片段,避免缓冲整个消息带来的过载。
      • 增加Host字段来实现虚拟主机技术。虚拟主机(virtual hosting)即共享主机(shared web hosting),可以利用虚拟技术把一台完整的服务器分成若干个主机,因此可以在单一主机上运行多个网站或服务。都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。此外,服务器应该接受以绝对路径标记的资源请求。
      • 新增100状态码——节约带宽客户端事先发送一个只带头域的请求,如果服务器因为权限拒绝了请求,就回送响应码401(Unauthorized);如果服务器接收此请求就回送响应码100,客户端就可以继续发送带实体的完整请求了。100 (Continue) 状态代码的使用,允许客户端在发request消息body之前先用request header试探一下server,看server要不要接收request body,再决定要不要发request body。
      • 提供了与身份认证、状态管理和Cache缓存等机制相关的请求头和响应头。
    • HTTP2.0
      • 支持二进制分帧image.png通过在应用层和传输层之间增加一个二进制分帧层,突破了HTTP1.1的性能限制、改进传输性能——HTTP2.0只是把原来HTTP1.x的header和body部分用frame重新封装了一层而已。HTTP/2 会将所有传输的信息分割为更小的消息和帧(frame),并对它们采用二进制格式的编码 ,减少了传输量。其中 HTTP1.x 的首部信息会被封装到 HEADER frame,而相应的 Request Body 则封装到 DATA frame 里面。
      • 多路复用——解决队头阻塞问题image.png
        • 概念流(stream):已建立连接上的双向字节流消息:与逻辑消息对应的完整的一系列数据帧帧(frame):HTTP2.0通信的最小单位,每个帧包含帧头部,至少也会标识出当前帧所属的流(stream id)
        • 所有的HTTP2.0通信都在一个TCP连接上完成,这个连接可以承载任意数量的双向数据流每个数据流以消息的形式发送,而消息由一或多个帧组成。这些帧可以乱序发送,然后再根据每个帧头部的流标识符(stream id)重新组装。HTTP2.0里每个数据流都可以设置优先级和依赖,优先级高的数据流会被服务器优先处理和返回给客户端,数据流还可以依赖其他的子数据流HTTP2.0实现了真正的并行传输,它能够在一个TCP连接上进行任意数量HTTP请求。而这个强大的功能则是基于“二进制分帧”的特性。
        • 多路复用和HTTP1.1中的管道化的区别image.png
      • 支持首部压缩Header Compression在HTTP1.x中,头部元数据都是以纯文本的形式发送的,通常会给每个请求增加500~800字节的负荷,如cookie:比较大且每次都重复发送,一般不存储信息,只是用来做状态记录和身份认证在HTTP2.0中,客户端和服务器端使用“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送;通信期间几乎不会改变的通用键-值对(用户代理、可接受的媒体类型,等等)只 需发送一次如果请求中不包含首部(例如对同一资源的轮询请求),那么 首部开销就是零字节。此时所有首部都自动使用之前请求发送的首部。如果首部发生变化了,那么只需要在Headers帧里面发送变化了的数据,新增或修改的首部帧会被追加到“首部表”。首部表在 HTTP 2.0 的连接存续期内始终存在,由客户端和服务器共同渐进地更新
      • 服务端推送(Server Push)服务器可以对一个客户端请求发送多个响应,即除了对最初请求的响应外,服务器还可以额外向客户端推送资源,而无需客户端明确地请求。