懒人版
http1.0每次请求都建立TCP断开TCP
http1.1只建立1个TCP连接,不断开,但是每个请求要按顺序排队 浏览器提供可以同时建立6-8个TCP连接,实现并发效果
http2只建立1个TCP连接,不断开,每个请求可以并发请求并且乱序响应
http1.0的问题
每个http请求都要重新建立TCP连接,并且是等待上一个TCP连接结束断开连接之后才建立下一个TCP连接
http1.1的问题
http1.1默认支持长连接(持久连接)来提升速度
http1.0则加一个 Connetion:keep-alive
即可开启
http1.1中手动关闭一个持久连接是 Connetion:close
长连接虽然支持一个TCP连接同时发送多个http请求(http管道机制),但是因为协议规定响应要按请求顺序返回,并且响应并不能同时返回,需要一个一个返回 因此会出现,前面的请求响应耗时导致虽然共用了1个TCP连接同时发起的请求,要等前面的响应完成才能响应(队头阻塞)
这样依然没能充分利用1个TCP连接的空闲时间
也正是因为1个TCP连接的请求效率在当下请求数越来越多,资源越来越大的互联网应用下是远远不够的 衍生了各种提升http并发性能的方法
- 浏览器支持1个域名同时建立6-8个TCP连接,发起请求的时候会自动选择1条TCP连接去发送
- 资源放在不同域名下,让应用支持更多的TCP连接数
- 图片资源做成base64减少请求的数量,小图合并成雪碧图减少请求的数量
- js资源打包成一个大chunk,来减少请求数量
- 资源懒加载
队头阻塞体现在真实场景是,一个响应久的请求会占用一个TCP连接,导致原本6个可用的连接变少
浏览器不允许更多的TCP连接原因是:假设一个客户端可以同时建立无限制的TCP连接,客户数一多同一时间会对服务器造成很大压力(极端情况也就是DDOS攻击)
http2的全双工模式
http1.1的队头阻塞等问题,证明通过允许多个TCP连接并不能解决问题,必须要1个TCP连接支持并发才能很好的提高性能(同时解决建立多个TCP连接的耗时)
虽然http1.1实现了tcp的长连接,在一个tcp链接通道中,我们可以连续处理多个http请求响应,但是这个处理过程是半双工模式,也就是同一时刻只能处理一个request的请求或者响应,后面的request必须等到前面的请求响应之后才能进行。
- 半双工:同一时间内,链接上只能有一方发送数据,另一方接受数据。
- 全双工:同一时间内,两端都可以发送或接受数据
http/2实现了全双工通信,具体表现为:浏览器针对同一个域名的资源,只建立一个tcp连接通道,所有的针对这个域名的请求全部在这个通道中完成
即多个完整的http请求同时发送,发送的过程是有一定顺序的整体,服务端接收处理后乱序响应
不再按请求顺序返回,直接乱序响应(也可以通过设置优先级制定顺序)
http2的多路复用
http2 基于把文本字符格式的http数改为流的形式,实现分割成帧,实现多个请求是交错发送,交错处理,在响应时组装成各自的响应
- 浏览器还是只支持6-8个TCP连接
- 同域名下所有通信都在单个连接上完成
- 单个连接上可以并行交错的请求和响应,之间互不干扰
- 该连接可以承载任意数量的双向数据流。
- 每个请求都可以带一个31bit的优先值,0表示最高优先级, 数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。
- 每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,根据帧首部的流标识可以重新组装
http2的并发效果
在上述http1.1和http2的区分下
在实际效果上会发现一些应用http2并没有提升多少速度
这里分析一下原因
- 同时建立6个TCP连接并且没有队头阻塞的情况下,http1.1与http2对比的性能损耗主要在建立另外5个TCP连接上
- 以及每6个连接的请求耗时如果时间都不长,或者要并发的数量其实没有很多,看上去就会和http2并发所有请求区别不会很大
- 假如我们是本地启前端静态服务器,并发很多请求在http1.1下会跟http2没多大区别,因为建立TCP连接很快,响应也很快
所以http2更明显的效果要体现在
- 多图场景
- 音视频场景
- ESM模块化场景,ESBuild等
http2的头部压缩
- 索引表 常用单词转为索引匹配
- 压缩编码HPACK
http2的二进制流: http1.1是字符串,流更容易分割
- HTTP/2 采用二进制格式传输数据,而非 HTTP 1.x 的文本格式,二进制协议解析起来更高效。 HTTP / 1 的请求和响应报文,都是由起始行,首部和实体正文(可选)组成,各部分之间以文本换行符分隔。HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。
http2的服务器推送
- 服务端可以主动把JS和CSS文件推送给客户端,而不需要客户端解析HTML时再发送这些请求。
用nodejs手写http2静态服务器和http1.1静态服务器对比
TODO:
总结
http2多路复用和http1.1的长连接keep-alive的区别
长连接1个TCP连接同一时间只能处理一个请求 只能有一方发送数据,另一方接受数据。 多路复用是1个TCP同一时间处理多个请求
为什么http1.1不能实现多路复用
字符串文本分割解析,在响应时如果处理多个请求,不能知道属于哪个请求的响应
在不改动 HTTP/1.1 的语义、⽅法、状态码、URI 以及⾸部字段等等的情况下, HTTP/2 是如何过渡到http1.1呢?
关键之⼀就是在应⽤层(HTTP/2)和传输层(TCP or UDP)之间增加⼀个⼆进制分帧层