公司的项目在打开作品时,加载资源速度很慢,正好这段时间比较闲,就打算看看能否优化一下。不看不知道,一看吓一跳。
竟然是串行请求
当我查到加载作品模块的代码时,我惊了。对于作品的图片加载,是通过foreach里写await去串行加载的。我一开始很难理解这么写的目的,后来问了同事,其实是为了防止超时。我们知道,一般浏览器如chrome是限制6个tcp连接的。如果一次性发送超过6个连接,那么第6个之后的请求会被挂起等待其余连接空闲才会继续响应。一股脑的并行请求,如果图片数量少还好,但遇到大作品,200张图片时,大概率会导致大部分的图片加载失败,因为超时了,服务器没有及时响应。那么有同学会问了,为什么不将超时设置长一点呢?一是你不知道设置到多长可以,每个用户网络情况不一,作品大小又不一,二是设计到服务器设置,可能前端不想去麻烦后端就自己解决了。
限制并行数量优化网络
那么该怎么做才能既不超时又能利用到并行的优势呢?限制并行数量!假如我们限制6个,当这6个请求响应结束后,才继续响应剩余的。这么一来就不会因为前段浏览器挂起请求而超时了,超时只会发生在服务器本身响应慢,或者客户端网络状态极差的情况下了。同时,我们还利用
到了并行的优势,通过测试,速度快了2倍-3倍,数据非常可观。对于限制并行数量可以用p-limit这个库或者自己写一个,并不难。
为什么并行会快这么多?
这个问题才是本篇的核心。刚才说了“并行的优势”,为什么并行会有优势呢?
省去了TCP连接时间?不对,不管是http1还是http2,要么有keep-alive,要么有多路复用,跟连接复用没关系。况且真是省去了连接时间,也做不到快2-3倍。
网络资源高度利用?我们知道带宽是恒定的,一个一个下载和一起去下载,总时间相差不多。因为带宽就这么多,怎么用都是一样的。
那到底为什么会快这么多??就当我想放弃准备摸鱼的时候,我刨根问底的精神还是被激发了,我打开了devtools,点开network,发现了这个:


前者是使用了并行,后者是串行。仔细观察一下,你会发现,在waterfall中两者的蓝绿占比是不同的。这里先说一下,绿色蓝色是啥玩意。绿色是指TTFB(time to first byte)第一个字节的时间。蓝色是download时间。可以理解TTFB是服务器响应时间,就是服务器拿到你的资源path后,在数据库或者往其他服务器查询这个资源并拿到的整个过程的时间。这个过程是不占用你的网络资源的,算是服务器I/O时间了。但download就不同了,他是传输数据的时间,会直接利用网络资源,所以可以看到,串行的时候,蓝色更少了。
这里还得继续深入,为什么服务器处理I/O的时间是一样的?一个请求,他是3s,多个请求,也是3s?我们知道I/O其实硬盘到内存,内存到硬盘的过程,那么TTFB也就是I/O的过程,(都扯到I/O了😂),I/O底层是怎么做的,这里就不深入了,至少我们清楚I/O是可以并行执行的。
到这里为止,我们终于清楚,并行为何有优势了。