Http协议发展
Http 0.9 1991年
鼻祖版本,存在以下问题
- 只指出get方法,不支持post,所以客户端能像服务端传输的信息量有限
- 不支持请求的header,不能指定版本号
- 服务器只有返回HTML字符串的能力
- 服务端响应后立刻关闭tcp连接。
Http 1.0 1996年
强化的部分
- 请求方法增加:post,delete,put,head
- 增加了请求头和响应头,可以指定版本号以及其他header信息
- 服务器可以返回更多内容格式:图片、音视频资源、二进制
仍存在的问题
- tcp连接复用性差,每个tcp连接只支持一次请求-响应。但是tcp本身3次握手4次挥手的成本就很高,所以1.0性能不高。
- 无状态
- 队头阻塞:此处的表现主要是,需要等前一个请求的响应到达后下一个请求才能发送。
Http 1.1 1997年
强化的部分
- 继续增加请求的方法:put,patch,options,delete
- 解决tcp连接复用性差的问题:增加长连接(connection字段的keep-alive值),tcp连接默认不关闭,可以被多个请求复用。然而还是需要等待前一个请求响应后,才能处理新请求。
- 解决队头阻塞:这里的做法是,可以不等响应,就可以继续发送后续的请求,但是响应时是按照顺序的,也就是说可能会被上一个响应阻塞。
- 机器复用:通过host字段指定服务器域名,从而可以将多个请求发往同一个服务器上的不同网站,提高机器复用。
总结:解决了请求端的阻塞问题,但是响应端仍会有阻塞的现象。
Http 2.0 2015年
2.0从性能角度出发,做了很多调整。
二进制分帧
将通信数据分解成二进制编码帧进行交换,每个帧对应特定数据流中特定消息,所有的帧和流都在一个tcp连接中复用。
通过二进制分帧,客户端和服务器可以将数据通过帧来互不影响的交错传出,最后根据帧头的流标识符进行组装,实现多路复用。
首部压缩
每个网页通常有100多个http请求,每个请求头300-500字节,总数据量在几十KB,在拥挤的链路中传输相同的数据不高效。
压缩采用hpack算法,维护一个首部表记录键值对,每次header只发送修改后的数据。
如上图所示,第一次请求时,全量发送header,第二次请求时,只需要发送修改的:path,极端情况下,如果没有修改,首部开销就是0字节。
服务端推送
这里的推送实际上是指:一问一答 -> 一问多答。
实际使用场景:服务器提前推送网络应用包含的多种资源,从而减少额外的延迟时间。
如图所示,客户端请求page.html,服务器端同时也推送了js和css文件。
总结:看起来http2.0通过二进制分帧解决了队头阻塞问题的同时,也通过首部压缩、服务器推送等手段大幅提高了性能。
Http 3.0 2018年
http2.0的问题在哪?在tcp上,tcp存在以下问题:
- 三次握手,建立连接时间长
- tcp窗口缓冲区,需要等待缓冲区内的数据全部到达,才能提交给应用层,丢包时需要阻塞,所以在tcp这个层面存在队头阻塞。
- 弱网环境下断连影响大
以上问题,似乎都可以使用udp来解决
- udp无连接,无建立和销毁成本
- udp数据包无队头阻塞问题
- 且不依赖于四元组{源IP,源端口,目标IP,目标端口}
goole在udp的基础上建立了QUIC协议,来增加udp的能力。
Quic的优势:
- 一个连接上多个流,流间互不影响,丢包的影响范围小。
- 在更短的RTT内发送应用数据,具体几个RTT的细节没有看。
- 连接迁移,如下图所示,4G网络切换到wifi时,IP地址会变化,依赖于IP地址的tcp连接需要重连。而基于唯一标识的quic无需重连。
参考资料: