Skip to content

懒人版

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)之间增加⼀个⼆进制分帧层

promise实现控制最大并发量,控制响应顺序

参考资料