HTTP1.1与HTTP2

HTTP1

Request GET / HTTP/1.0 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) Accept: */* Response HTTP/1.0 200 OK Content-Type: text/plain Content-Length: 137682 Expires: Thu, 05 Dec 1997 16:00:00 GMT Last-Modified: Wed, 5 August 1996 15:55:28 GMT Server: Apache 0.84 <html> <body>Hellow World</body> </html>

以上为一个简单的HTTP请求。

由于HTTP1.x ResponseHeader必须为文本格式,而ResponseBody可以为任意格式,因此需要在Content-Type指明返回的是什么格式(MIME Type)。 RequestHeader中的Accept则指明了客户端可以接受什么格式。 由于ResponseBody可以是任意格式,因此可以数据压缩后再发送,Content-Encoding指明了数据压缩的方法。

Content-Encoding: gzip Content-Encoding: compress Content-Encoding: deflate

客户端请求时,也可指明自己接受哪些压缩方法

Accept-Encoding: gzip, deflate

keep-alive长连接

HTTP1.1引入了长连接,即在一个TCP连接中可以发送多个请求。TCP连接默认不关闭,可以不用声明Connection: keep-alive

客户端或服务端发现对方一段时间没活动后就可以主动关闭连接。不过规范的做法是,客户端在最后一个请求时发送Connection: close,明确服务器关闭TCP连接。

HTTP1.1引入了管道机制(pipelining),同一个TCP连接中的客户端可以同时发送多个请求。以前需要先发送A请求,等待A请求返回再发送B请求,现在可以同时发送A和B请求,但是服务端还是会依次返回,先回应A,再回应B。

由于可以传回多个回应,因此需要一个字段区分数据包属于哪个回应,因此需要

Content-length: 3495

以上代码告诉浏览器本次回应长度为3495字节,之后的字节属于下个回应。

分块传输代码

但是HTTP1.1也可使用另一种传输方式:分块传输代码(chunked transfer encoding),避免耗时长的操作要等服务器所有操作完成才能发送。分块发送需要Header中有Transfer-Encoding字段。

Transfer-Encoding: chunked

在每个非空数据块前会有一个16进制值,表示该块长度。最后一个是大小为0的块,表示该请求回应完了。

即根据Content-length或长度为0的chunk可以划分消息边界。

虽然HTTP1.1有了长连接,但是所有请求依然是按次返回的,即B请求还是得等A请求返回了才能返回,假如A请求是个非常耗时的操作,会造成队头堵塞(Head-of-line blocking)

为了避免该问题,可以减少请求数,或同时多开持久连接(对于大多数浏览器,对于同一域名,允许同时建立6个持久连接)

HTTP2

二进制头部与消息体

HTTP2第一个新特性是二进制协议。HTTP2的头部和数据体都是二进制,统称为帧(frame)

多路复用

同时HTTP2可以多路复用。客户端和服务端都可同时发送多个请求或回应,比如可以先回应A请求的一部分,接着回应B请求,最后回应A请求的剩下部分。

由于多路复用的特性,因此HTTP2需要对每个数据包做标记,标记它属于哪个回应(数据流),每个数据流有一个唯一id。协议规定,客户端发出的数据流id为奇数,服务端发出的数据流id为偶数。

取消数据流

同时HTTP2可以取消数据流。数据流发送一半时客户端和服务端都可以发送一个RST-STREAM帧,取消该数据流。而在HTTP1.1中取消数据流只能关闭TCP连接。同时客户端可以指定数据流优先级,服务器可以根据优先级决定回应顺序。

头部压缩

HTTP2引入了头信息压缩机制。一方面头信息使用hpck协议压缩。另一方面客户端和服务端都维护一张头信息表,对于相同Header字段只发送索引,不再发送重复字段,只发送更新了的字段。

服务端主动推送

HTTP2允许服务器主动推送,比如当客户端请求index.html时,服务端可以主动推送index.css,index.js。服务器会先发送PUSH_PROMISE帧,该帧只包含预推送资源的首部。如果客户端对此无意见,服务端就会发送DATA帧。客户端也可以拒绝推送。当客户端接收到这些文件时,当下次请求这些文件时就可以直接从缓存中读取。

评论加载中 (ง •̀ω•́)ง