1. 版本介绍http协议发展到现在也有了四个版本分别是http/0.9 ➡️ http1.0 ➡️ http/1.1 ➡️ http2.02. 各个版本之间的差异有哪些1⃣️http/0.9这个版本之最初的http协议版本功能尚未完善相对现在的协议来说非常的简陋方法也只支持GET请求资源也只支持html格式的资源2⃣️http/1.0http/1.0的协议在请求时必须在尾部加上添加版本号字段必须包含头部信息 在方法上也增加了POST 和hEAD方法请求的资源也不再只是html格式根据Content-Type可以支持多种数据格式即MIME多用途互联网邮件扩展例如text/html、image/jpg等同时也开始支持cache就是当客户端在规定时间内访问同一网站直接访问cache即可。但是1.0版本的工作方式是每次TCP连接只能发送一个请求当服务器响应后就会关闭这次连接下一个请求需要再次建立TCP连接就是不支持keepalive。TCP连接的新建成本很高因为需要客户端和服务器三次握手并且开始时发送速率较慢slow start。所以HTTP 1.0版本的性能比较差。随着网页加载的外部资源越来越多这个问题就愈发突出了。为了解决这个问题有些浏览器在请求时用了一个非标准的Connection字段Connection: keep-alive这个字段要求服务器不要关闭TCP连接以便其他请求复用。服务器同样回应这个字段。一个可以复用的TCP连接就建立了直到客户端或服务器主动关闭连接。但是这不是标准字段不同实现的行为可能不一致因此不是根本的解决办法。content-type字段关于字符的编码1.0版规定头信息必须是 ASCII 码后面的数据可以是任何格式。因此服务器回应的时候必须告诉客户端数据是什么格式这就是Content-Type字段的作用。常见的Content-Type字段的值text/plaintext/htmltext/cssimage/jpegimage/pngimage/svgxmlaudio/mp4video/mp4application/javascriptapplication/pdfapplication/zipapplication/atomxml这些数据类型总称为MIME type每个值包括一级类型和二级类型之间用斜杠分隔。除了预定义的类型厂商也可以自定义类型application/vnd.debian.binary-package表明发送的是Debian系统的二进制数据包MIME type还可以在尾部使用分号添加参数。Content-Type: text/html; charsetutf-8上面的类型表明发送的是网页而且编码是UTF-8客户端请求的时候可以使用Accept字段声明自己可以接受哪些数据格式Accept: */*代码中客户端声明自己可以接受任何格式的数据MIME type不仅用在HTTP协议还可以用在其他地方比如HTML网页。Content-Encoding 字段由于发送的数据可以是任何格式因此可以把数据压缩后再发送。Content-Encoding字段说明数据的压缩方法。Content-Encoding: gzipContent-Encoding: compressContent-Encoding: deflate客户端在请求时用Accept-Encoding字段说明自己可以接受哪些压缩方法。Accept-Encoding: gzip, deflate3⃣️http/1.01.1 版的最大变化就是引入了持久连接persistent connection即TCP连接默认不关闭可以被多个请求复用不用声明Connection: keep-alive。解决了1.0版本的keepalive问题;1.1版本加入了持久连接一个TCP连接可以允许多个HTTP请求客户端和服务器发现对方一段时间没有活动就可以主动关闭连接。不过规范的做法是客户端在最后一个请求时发送Connection: close明确要求服务器关闭TCP连接。目前对于同一个域名大多数浏览器允许同时建立6个持久连接。降低了延迟同时提高了带宽的利用率。加入了管道机制在同一个TCP连接里允许多个请求同时发送增加了并发性进一步改善了HTTP协议的效率举例来说客户端需要请求两个资源。以前的做法是在同一个TCP连接里面先发送A请求然后等待服务器做出回应收到后再发出B请求。管道机制则是允许浏览器同时发出A请求和B请求但是服务器还是按照顺序先回应A请求完成后再回应B请求。Content-Length 字段一个TCP连接现在可以传送多个回应势必就要有一种机制区分数据包是属于哪一个回应的。这就是Content-length字段的作用声明本次回应的数据长度。在1.0版中Content-Length字段不是必需的因为浏览器发现服务器关闭了TCP连接就表明收到的数据包已经全了。分块传输编码使用Content-Length字段的前提条件是服务器发送回应之前必须知道回应的数据长度。对于一些很耗时的动态操作来说这意味着服务器要等到所有操作完成才能发送数据显然这样的效率不高。更好的处理方法是产生一块数据就发送一块采用流模式stream取代缓存模式buffer。因此1.1版规定可以不使用Content-Length字段而使用分块传输编码chunked transfer encoding。只要请求或回应的头信息有Transfer-Encoding字段就表明回应将由数量未定的数据块组成。(Transfer-Encoding: chunked)每个非空的数据块之前会有一个16进制的数值表示这个块的长度。最后是一个大小为0的块就表示本次回应的数据发送完了。下面是一个例子。HTTP/1.1 200 OKContent-Type: text/plainTransfer-Encoding: chunked25This is the data in the first chunk1Cand this is the second one3con8sequence0新增了请求方式PUT、PATCH、OPTIONS、DELETE等;另外客户端请求的头信息新增了Host字段用来指定服务器的域名。在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址因此请求消息中的URL并没有传递主机名hostname。但随着虚拟主机技术的发展在一台物理服务器上可以存在多个虚拟主机Multi-homed Web Servers并且它们共享一个IP地址。(Host: www.example.com)有了Host字段就可以将请求发往同一台服务器上的不同网站为虚拟主机的兴起打下了基础。实现了在一台WEB服务器上可以在同一个IP地址和端口号上使用不同的主机名来创建多个虚拟WEB站点。也即是说web server上的多个虚拟站点可以共享同一个ip和端口。且请求消息中如果没有Host头域会报告一个错误400 Bad Request。虽然1.1版允许复用TCP连接但是同一个TCP连接里面所有的数据通信是按次序进行的。服务端是按队列顺序处理请求的服务器只有处理完一个回应才会进行下一个回应。假如前面的请求处理时间很长后面就会有许多请求排队等着这样就造成了“队头阻塞”的问题同时HTTP是无状态的连接因此每次请求都需要添加重复的字段降低了带宽的利用率。多路复用带来一个新的问题是在连接共享的基础之上有可能会导致关键请求被阻塞。SPDY允许给每个request设置优先级这样重要的请求就会优先得到响应。比如浏览器加载首页首页的html内容应该优先展示之后才是各种静态资源文件脚本文件等加载这样可以保证用户能第一时间看到网页内容。为了避免这个问题只有两种方法一是减少请求数二是同时多开持久连接。这导致了很多的网页优化技巧比如合并脚本和样式表、将图片嵌入CSS代码、域名分片domain sharding等等。如果HTTP协议设计得更好一些这些额外的工作是可以避免的。100(Continue) Status(节约带宽)HTTP/1.1加入了一个新的状态码100Continue。客户端事先发送一个只带头域的请求如果服务器因为权限拒绝了请求就回送响应码401Unauthorized如果服务器接收此请求就回送响应码100客户端就可以继续发送带实体的完整请求了。100 (Continue) 状态代码的使用允许客户端在发request消息body之前先用request header试探一下server看server要不要接收request body再决定要不要发request body。HTTP/1.1在1.0的基础上加入了一些cache的新特性当缓存对象的Age超过Expire时变为stale对象cache不需要直接抛弃stale对象而是与源服务器进行重新激活revalidation。HTTP 1.1支持只发送header信息(不带任何body信息)如果服务器认为客户端有权限请求服务器则返回100否则返回401。客户端如果接受到100才开始把请求body发送到服务器。这样当服务器返回401的时候客户端就可以不用发送请求body了节约了带宽。HTTP1.1还有身份认证机制许多web站点要求用户提供一个用户名—口令对才能访问存放在其服务器中的文档这种要求称为身份认证(authentication)。HTTP提供特殊的状态码和头部来帮助Web站点执行身份认证。HTTP支持传送内容的一部分。这样当客户端已经有一部分的资源后只需要跟服务器请求另外的部分资源即可。这是支持文件断点续传的基础。HTTP/1.1支持文件断点续传RANGE:bytesHTTP/1.0每次传送文件都是从文件头开始即0字节处开始。RANGE:bytesXXXX表示要求服务器从文件XXXX字节处开始传送断点续传。即返回码是206Partial Content在HTTP1.1中新增了24个错误状态响应码如409Conflict表示请求的资源与资源的当前状态发生冲突410Gone表示服务器上的某个资源被永久性的删除。4⃣️ http/2.0为了解决1.1版本利用率不高的问题提出了HTTP/2.0版本。增加双工模式即不仅客户端能够同时发送多个请求服务端也能同时处理多个请求解决了队头堵塞的问题HTTP2.0使用了多路复用的技术做到同一个连接并发处理多个请求而且并发请求的数量比HTTP1.1大了好几个数量级HTTP请求和响应中状态行和请求/响应头都是些信息字段并没有真正的数据因此在2.0版本中将所有的信息字段建立一张表为表中的每个字段建立索引客户端和服务端共同使用这个表他们之间就以索引号来表示信息字段这样就避免了1.0旧版本的重复繁琐的字段并以压缩的方式传输提高利用率也增加服务器推送的功能即不经请求服务端主动向客户端发送数据。注意当前主流的协议版本还是HTTP/1.1版本。二进制协议HTTP/1.1 版的头信息肯定是文本ASCII编码数据体可以是文本也可以是二进制。HTTP/2 则是一个彻底的二进制协议头信息和数据体都是二进制并且统称为帧frame头信息帧和数据帧。二进制协议的一个好处是可以定义额外的帧。HTTP/2 定义了近十种帧为将来的高级应用打好了基础。如果使用文本实现这种功能解析数据将会变得非常麻烦二进制解析则方便得多。多工HTTP/2 复用TCP连接在一个连接里客户端和浏览器都可以同时发送多个请求或回应而且不用按照顺序一一对应这样就避免了队头堵塞。举例来说在一个TCP连接里面服务器同时收到了A请求和B请求于是先回应A请求结果发现处理过程非常耗时于是就发送A请求已经处理好的部分 接着回应B请求完成后再发送A请求剩下的部分。这样双向的、实时的通信就叫做多工Multiplexing。数据流因为 HTTP/2 的数据包是不按顺序发送的同一个连接里面连续的数据包可能属于不同的回应。因此必须要对数据包做标记指出它属于哪个回应。HTTP/2 将每个请求或回应的所有数据包称为一个数据流stream。每个数据流都有一个独一无二的编号。数据包发送的时候都必须标记数据流ID用来区分它属于哪个数据流。另外还规定客户端发出的数据流ID一律为奇数服务器发出的ID为偶数。数据流发送到一半的时候客户端和服务器都可以发送信号RST_STREAM帧取消这个数据流。1.1版取消数据流的唯一方法就是关闭TCP连接。这就是说HTTP/2 可以取消某一次请求同时保证TCP连接还打开着可以被其他请求使用。客户端还可以指定数据流的优先级。优先级越高服务器就会越早回应。头信息压缩HTTP 协议不带有状态每次请求都必须附上所有信息。所以请求的很多字段都是重复的比如Cookie和User Agent一模一样的内容每次请求都必须附带这会浪费很多带宽也影响速度。HTTP/2 对这一点做了优化引入了头信息压缩机制header compression。一方面头信息使用gzip或compress压缩后再发送另一方面客户端和服务器同时维护一张头信息表所有字段都会存入这个表生成一个索引号以后就不发送同样字段了只发送索引号这样就提高速度了。服务器推送HTTP/2 允许服务器未经请求主动向客户端发送资源这叫做服务器推送server push。就是说当我们对支持HTTP2.0的web server请求数据的时候服务器会顺便把一些客户端需要的资源一起推送到客户端免得客户端再次创建连接发送请求到服务器端获取。这种方式非常合适加载静态资源。服务器端推送的这些资源其实存在客户端的某处地方客户端直接从本地加载这些资源就可以了不用走网络速度自然是快很多的。常见场景是客户端请求一个网页这个网页里面包含很多静态资源。正常情况下客户端必须收到网页后解析HTML源码发现有静态资源再发出静态资源请求。其实服务器可以预期到客户端请求网页后很可能会再请求静态资源所以就主动把这些静态资源随着网页一起发给客户端了。服务端推送能把客户端所需要的资源伴随着index.html一起发送到客户端省去了客户端重复请求的步骤。正因为没有发起请求建立连接等操作所以静态资源通过服务端推送的方式可以极大地提升速度。HTTP 性能优化的关键并不在于高带宽而是低延迟。TCP 连接会随着时间进行自我「调谐」起初会限制连接的最大速度如果数据成功传输会随着时间的推移提高传输的速度。这种调谐则被称为 TCP 慢启动(拥塞控制)。由于这种原因让原本就具有突发性和短时性的 HTTP 连接变的十分低效。HTTP/2 通过让所有数据流共用同一个连接可以更有效地使用 TCP 连接让高带宽也能真正的服务于 HTTP 的性能提升。