本文是郑老师的高级计算机网络的学习笔记,配图来自小林coding和郑老师的PPT
HTTP的迭代
HTTP1.0
HTTP1.0 支持GET,POST,DELTE,PUT,HEAD等方法,有报文头和报文体的区分。 HTTP1.0是非持久连接:在TCP的连接上只有一个对象的请求和响应,之后就关闭,效率非常低下。带宽利用率非常低。
HTTP1.1
HTTP1.1支持持久连接,在一个TCP连接上可以发送请求多个对象和响应(一开始请求网页,可以得到元数据,比如需要10个对象,接下来可以再发送10个请求过去,而不中断TCP连接)。 支持: 1) pipeline 2)缓存(if-modify-since字段) 3) 断点续传(支持请求对象的一部分)
问题: 存在HTTP头端阻塞。
HTTP头端阻塞:客户端向服务端发送多个对象的请求(main.js, style.css(这个文件包含两个包:s1,s2))。服务端返回这些对象时比如是按(s1, main.js, s2)这样返回,如果main.js丢失了,会导致s2阻塞,无法交付给应用进程。 这个本质是因为TCP阻塞。
HTTP/2
HTTP2引入了很多特性,比如流和多路复用,头部压缩,服务器推送。
首先不同于HTTP1.x,HTTP/2采用了二进制编码传输,而不是文本形式传输。二进制数据解析起来会更加高效,HTTP/2将请求和响应数据分割成更小的帧,并且采用二进制编码。
头部压缩: HTTP1.x的头部报文中,有很多字段其实在一次连接中是不会改变的,但是每次传输都得带上这些数据(cookies,User-Agent等)非常耗费带宽,降低传输速率。并且在大量的请求数据中,很多字段也是重复出现的,HTTP/2对这些数据进行了压缩,来提高传输效率。 —— 实现的原理是客户端和服务端都维护了一张表,来索引一些不常变化的字段,并且通过Huffman编码来进行压缩,具体我会专门出一篇文来学习HTTP2的原理。
多路复用: HTTP/2中引入了Stream的概念,它支持多个Streams复用同一条TCP连接,从而解决了HTTP1中的头部阻塞的问题(注意:这里解决的是HTTP中的头部阻塞问题,而不是TCP中,因此本质的问题并没有被解决)。什么意思呢?以请求main.js,style.css(包含s1,s2)为例,main.js和s1,s2的Stream标识不一样,所以就算main.js丢失了,s2还是可以交付给应用程序。(这里是组装HTTP消息,如果TCP阻塞了,依然会有头部阻塞)。
服务器推送: HTTP/2支持服务器推送功能,就是当客户请求数据时,服务端会根据客户请求的数据,主动推送客户可能请求的数据到客户端。比如客户请求HTML文件,得到网页的大概框架,还需要CSS文件来进行渲染,那么再HTTP1.x客户就要发送两个请求,但是在HTTP/2,服务端会在客户请求HTML文件时,主动推送css文件给客户,减少了消息传递的时间。
问题: 依旧无法解决TCP头部阻塞的问题。并且TLS/TCP连接需要3RTT,十分耗时。
HTTP/3
HTTP/2虽然很好地解决了HTTP层的头部阻塞问题,但是因为它的底层依然是TCP,TCP的头部阻塞没办法解决,再加上每次进行连接时,需要进行TCP握手和TLS握手,非常消耗时间。为了解决这些问题,基于QUIC的HTTP/3协议出现,解决了这些问题。QUIC是基于UDP的应用层协议,运作在HTTP和UDP之间。因为UDP不可靠,所以关于可靠通信的性质就在QUIC这里实现。
下面会先比较一下TCP/UDP应用的优缺点,再详细阐述QUIC出现的必要性和原理。
TCP/UDP的缺点
在传统应用(现代大多数应用)的开发主要是依赖于TCP或者UDP进行开发。
TCP
TCP的特性: 拥塞控制、可靠传输、流量控制
使用TCP的好处: 便捷,TCP帮你做好了所有可靠通信的支持,开发只需关注应用层。
使用TCP的坏处: 虽然TCP帮应用层开发人员做了很多,那就意味着我们需要忍受TCP带来的缺点:握手次数太多,慢启动,基于丢失的拥塞控制吞吐抖动。TCP实现可靠性的恢复时间长。
因为TCP是内核态实现,要对TCP进行修改的难度十分巨大。
UDP
UDP的特性: 区分进程,不可靠,无拥塞控制,无流量控制,不安全等
UDP的好处: 快速,轻载,没有性能限制
UDP的坏处: 简陋,不安全,不可靠,基于UDP的应用开发量巨大。
可以看出,无论是TCP还是UDP都无法满足现代应用的要求:快速,安全,可靠。并且由于它们是内核态实现,并且几乎所有网络设备都支持,对这两个协议进行改造非常困难。我们只能在用户态进行开发来增强TCP/UDP。
QUIC概述
我对QUIC的理解就是: 取其精华,去其糟粕。
因为HTTP/2无法消除头部阻塞以及每次能够传输数据之前都需要TLS/TCP的连接,十分耗时。为了解决这个问题,直接修改TCP/UDP是困难的,或者在传输层再加一个新协议也是困难的,因为这涉及庞大的基建。因此直接在HTTP/2和传输层直接加一个协议,就是QUIC,它结合了HTTP/2的高级特性(多路复用,头部压缩,服务器推送等特性),TCP的特性:拥塞控制,可靠传输,TLS的安全性以及UDP的快速传输(不会在传输层导致头部阻塞)。
在应用层添加QUIC也是为了方便其它应用层协议。
QUIC的特性:
- 握手延迟低,避免头部阻塞,高效地可靠恢复,模块化拥塞控制(可以热插拔地选择拥塞控制算法)。支持连接迁移(如果传统TCP,由于需要四元组的标识,当其中一方的IP发生变化时,连接就会断开)。 —— 提高了HTTP传输效率。
- 安全性,与TLS1.3高效协作,绝大部分头部和所有数据都被加密,所有信息都是认证的,每次会话使用新密钥。
- 在用户态,方便部署(以库/SDK的形式)。
- 避免网络middlebox的干预。——有些防火墙会过滤掉一些可疑的数据,QUIC使用UDP,只要防火墙不过滤UDP的数据报,基于QUIC的数据就不会被过滤。
QUIC原理
QUIC的架构
QUIC提供了一个连接的概念(Connection)这个连接不像TCP依赖四元组,而是通过连接ID来标记通信的两个端点。
流stream: 一个完整请求和响应的字节流。一个连接上可以多个流(单向/双向)。流由62位stream id表示。最低两位:1位标识单双向,1位标识流的发起者。
帧frame: 流中传输数据的单位——分为数据帧和控制帧。
QUIC分组 连接传输的数据单位,UDP数据包载荷中有若干个分组,分组里包含了若干帧。
复用HTTP/2多路复用
快速握手
连接迁移
拥塞控制和流量控制
丢失恢复的高效实现
安全性
参考资料: