受欢迎的博客标签

从网络通信角度谈web性能优化(从输入url到浏览器开始渲染页面中间都发生了什么)

Published

衡量一个网站的性能有多个指标,DNS解析时间,TCP链接时间,HTTP重定向时间,等待服务器响应时间等等,从用户角度来看,就可以归结为该网站访问速度的快慢。也就是说性能等于网站的访问速度。


早些年Amazon曾经做过一个统计:网页加载时间每延长1秒钟,一年将减少16亿美元的营收。(16亿美元是一个什么概念呢?2015年,百度全年的总营收约100亿美元!)。


鉴于性能的重要性,于是我们便经常看到许多记录提升访问速度的方法的文章:减少http请求,雪碧图,压缩文件等等,看了这些文章后,博主了解了一些比较普遍的提升性能的方法,但是还不明白为啥这样能提升速度呀!


作为一名有志青年,博主认为,不仅要知其然,还要知其所以然。在查阅大量书籍和博文后,终于明白了其中的玄机,特此记录下来,与大家分享。

接下来,我们首先来深入理解一个浏览器与互联网的通信过程,然后分析每个过程所占时间的多少,以及哪些过程的时间是可以减少的,再说明通过怎样的方法可以减少这些时间,以此来缩小网站总的加载时间,提升网站的访问速度。

 

cloudflare Speed test result

https://dash.cloudflare.com/dfc09f04ef21f0f5d7efab13036d41aa/iaspnetcore.com/speed

Time to First Byte TTFB

First Contentful Paint

First Meaningful Paint

First Interactive

Speed Index

Total Load time

 

 

 

Time to First Byte

TTFB 是 Time to First Byte 的缩写,指的是浏览器开始收到服务器响应数据的时间(后台处理时间+重定向时间),是反映服务端响应速度的重要指标。就像你问朋友了一个问题,你的朋友思考了一会儿才给你答案,你朋友思考的时间就相当于 TTFB。你朋友思考的时间越短,就说明你朋友越聪明或者对你的问题越熟悉。对服务器来说,TTFB 时间越短,就说明服务器响应越快。

 

First Contentful Paint

首次内容绘制(First Contentful Paint,FCP)
这是当用户看见一些“内容”元素被绘制在页面上的时间点。和白屏是不一样的,它可以是文本的首次出现,或者 SVG 的首次出现,或者 Canvas 的首次出现等等。

因此,用户可能会产生疑问,它正在运行吗? 页面是否在他(她)键入 URL 并按 enter 键后开始加载了呢

 

First Meaningful Paint

首次有意义绘制(First Meaningful Paint,FMP)
这是指页面主要内容出现在屏幕上的时间点。

主要内容是什么?

博客的标题和文本
搜索引擎的搜索文本
对于电子商务产品来说重要的图片
展示的时候。

但如果展示的是

下拉菜单或类似的东西
无样式内容闪烁(FOUC)
导航条或页面标题
则不计算在主要内容之内。

FMP = 最大布局变化时的绘制

 

Speed Index是显示页面的可见部分的平均时间。它以毫秒为单位表示,会受视图端口大小的影响。
  Speed Index已于2012年4月添加到WebPagetest,衡量页面内容填充的速度(越低越好)。它特别适用于比较不同页面之间的差别(在优化之前/之后,我的网站与竞争对手等),与其它指标(Load Time,Start Render等)结合使用,可以更好地了解网站的性能 。

 

网站加载 Waiting (TTFB) 时间过长的原因和解决办法

 

从输入url到浏览器开始渲染页面中间都发生了什么

互联网内各网络设备间的通信都遵循TCP/IP协议,利用TCP/IP协议族进行网络通信时,会通过分层顺序与对方进行通信。分层由高到低分别为:应用层、传输层、网络层、数据链路层。发送端从应用层往下走,接收端从数据链路层网上走。如图所示

 

  1. 在浏览器中输入url
    用户输入url,如www.zhihu.com。其中https是协议,//后面的是网络地址,网…

  2. 浏览器查询缓存
    如果存在有效的缓存,则跳至第11步的渲染阶段。

  3. 应用层DNS解析域名
    域名是为了方便人类记忆,但计算机不能很好的处理域名,因为IP地址的长度是固定的32位(IPv6是128位),而域名的长度不固定,机器处理起来比较困难,因此需要有一个辅助系统提供域名到IP地址的映射,这个辅助系统就是DNS(Domain Name System)。 在收到一个域名后,客户端会先检查本地是否有对应的IP地址,若找到则返回响应的IP地址。若没找到则请求上级DNS服务器,直至找到根域。最终得到域名对应的IP地址,存在负载均衡时同一域名返回IP可能不同,所以IP地址才是是计算机在网络中的唯一标识。

  4. 应用层发送http请求
    http协议是用于客户端与服务器端通信的一种协议,它是通过请求和响应这种方式来实现通信的。HTTP请求包括请求报头和请求主体两个部分,其中请求报头包含了至关重要的信息,比如请求的方法(GET,POST,PUT,DELETE,CONNECT…)、目标url、遵循的协议(http / https / ftp…),以及客户端是否发送cookie等。

  5. SSL/TLS安全传输协议
    它是位于传输层之上的一个安全套接层也就是https中的’s’,确保了(1)所有信息都是加密传播的,第三方无法窃听(2)具有校验机制,一旦被篡改,通信双方会立刻发现(3)配备身份证书,防止身份被发现。
    为网络通信提供安全保障。

  6. 传输层用TCP协议传输报文
    位于传输层的TCP协议为传输报文提供可靠的字节流服务。它为了方便传输,将大块的数据分割成以报文段为单位的数据包,并为他们编号,方便服务器接收时能正确的快速还原报文信息。TCP协议通过三次握手来建立连接,通过四次挥手断开连接,保证了传输的安全可靠,下面的两张图和那后地解释了三次握手和四次挥手。



  7. 网络层IP协议查询MAC地址
    IP协议的作用是把TCP分割好的各种数据包传送给接收方,这时就需要接收方的MAC 地址,也就是物理地址。IP地址和MAC地址是一一对应的关系,一个网络设备的IP地址可以更换,但是MAC地址一般是固定不变的。ARP协议可以将IP地址解析成对应的MAC地址。当通信的双方不在同一个局域网时,需要多次中转才能到达最终的目标,在中转的过程中需要通过下一个中转站的MAC地址来搜索下一个中转目标,路由提供这种中转服务

  8. 数据到达数据链路层被处理包装

    在找到对方的MAC地址后,就将数据发送到数据链路层,数据链路层负责三件事:封装成帧,透明传输,差错检测。

  1. 物理层传输到达服务器端
    数据进入物理层到达服务器后,再经历3-7的相反操作:在链路层接收到数据包,再层层向上直到应用层。这过程中包括在运输层通过TCP协议将分段的数据包重新组成原来的HTTP请求报文。

  2. 服务器响应
    服务接收到客户端发送的HTTP请求后,查找客户端请求的资源,并返回响应报文,响应报文中包括一个重要的信息——状态码。状态码由三位数字组成,其中比较常见的是200 OK表示请求成功。301表示永久重定向,即请求的资源已经永久转移到新的位置。在返回301状态码的同时,响应报文也会附带重定向的url,客户端接收到后将http请求的url做相应的改变再重新发送。

  3. 客户端接收响应并渲染页面
    服务器的响应到达客户端后,浏览器会根据接收到的数据渲染页面。渲染阶段也有许多改善性能的方案,本文的重点不在这里,下次在另一篇文章里细说。

以上就是网络通信的整个过程,深究起来极其复杂,用到的协议也是非常多,不得不由衷地佩服先人的智慧!

chrome开发者模式Network下分析各个过程对应时间

chrome浏览器下按F12打开开发者工具,找到第四栏的network,在浏览器上方地址栏输入一个自己从未访问过的url,目的是保证请求的内容没被缓存在本地(为此,博主还清理了一波浏览器缓存(;′⌒`),伤心)。
整体大概是这样:

找一个有代表性的请求,如上图红色框所示,将鼠标放在黄色箭头所指的地方,会浮现该请求timeline的详情,如下图所示

这张详情图中可谓是藏了不少有价值的信息呢( •̀ ω •́ )✧,注意看咯!

  1. Resource scheduling(红色圈圈3)
    第一部分首先是资源调度的时间。
    红色圈圈告诉我们Queued at 214.06ms,在214.06 ms 时开始排队。排了0.57ms后(圈圈4),就Started at 214.63ms(圈圈2),也就是说资源调度结束后就开始处理该指令了。
    据chrome官方解释,导致Queueing的原因有以下几种:

    • 请求已被渲染引擎推迟,因为该请求的优先级被视为低于关键资源(例如脚本/样式)的优先级。 图像经常发生这种情况。
    • 请求已被暂停,以等待将要释放的不可用 TCP 套接字。
    • 请求已被暂停,因为在 HTTP 1 上,浏览器仅允许每个源拥有六个 TCP 连接。
    • 生成磁盘缓存条目所用的时间(通常非常迅速)
  2. Connection Start(圈圈5)
    资源调度后就要开始建立链接了。
    圈圈6 Stalled代表 请求等待发送所用的时间,此时间包含第一部分中的第二步:查看浏览器缓存所用的时间,下图是刷新后一个“from disk cache”文件的详情图,可以很好地证明这一点。

    圈圈7 Proxy negotiation 代表与代理服务器协商的时间
    圈圈8 DNS Lookup 执行 DNS 查询所用的时间。 页面上的每一个新域都需要完整的往返才能执行 DNS 查询。对应于第一部分中的“应用层DNS解析域名”时间
    圈圈9 Initial Connection 初始化连接所用的时间,包括 TCP 握手/重试和协商 SSL 的时间。对应于第一部分的6和7
    圈圈10 SSL 完成SSL握手所需要的时间,对应于第一部分的5

    机智的你是不是已经发现建立链接的时间刚好对应于第一部分中的3-

  3. Request/Response
    通信链接建立后,就可以发送请求了,服务器处理后返回响应,客户端再根据响应内容下一步处理

    圈圈11 Request sent 发送请求的时间,这个是非常快的
    圈圈12 Waiting(TTFB)等待服务器初始响应所用的时间,也称为至第一字节的时间。 此时间将捕捉到服务器往返的延迟时间,以及等待服务器传送响应所用的时间。
    最后是 Content Download,接受(下载)响应数据所需要的时间。

可以发现,详情图中的时间顺序和第一张网络模型示意图刚好一一对应,只有TCP/IP连接建立完成后,才能再建立SSL/TLS,最后才可用http协议请求/响应。

到这里,想必你已经明白了一次完整的请求需要经历的步骤和耗费的时间,那么这些时间中有哪些是可以人为减少的呢?我们可以通过怎样的方式来减少这些时间来提高性能呢?
看下面

优化web性能的若干方法

  1. 减少http的请求数降低connection的时间
    由上面的详情图可以看到,如果本地没有缓存时,许多时间都花在了第二步Connection Start 建立链接上,只有少部分花在了Content Download上。那好,现在如果我们把两个文件合并成一个,就可以用一次请求代替之前的两次请求,理论上是不是就节约了一次Connection的时间了?合并的文件越多,节约的时间就越多。
    所以我们可以把图片,css,js等一些可以合并的文件尽量合并来减少http的请求数,降低总的connection的时间。
    细心的朋友可能会发现,有的请求是几乎没有connection的时间的,它们的详情图长这样:

    查看request header发现其中有一个这样的键值对:

    对,就是因为它,http的keep-alive可以在一定的时间内保证连接的可复用性,减少连接时间,但它的期限是有限的,可以看到network下的请求中还是有若干次请求是有connection的时间的,所以合并文件还是必须的。

  1. 压缩文件降低content download的时间
    上图中content download的时间不算多,只有20.47ms ,但它还是可以被减少的呀,如果我们压缩了该文件,在相同物理环境下,它会变得更少呀!能减少一点是一点嘛。
    而且在一些项目中,部分文件可达几百kb,这时content download的时间就不止20ms了,所以压缩后还是能减少不少时间的。
    所以项目上线前,像一些图片啦,css,js啦,能压缩的还是尽量压缩。

  2. 使用浏览器缓存
    把网站里面更新频率比较低的静态资源缓存在浏览器中,能够很好地提升速度。事实证明的确如此,( •̀ ω •́ )✧

    毕竟对于几百K的文件硬盘还是可以秒读的嘛。
    通过设置 http 头里的 Cache-Control 和 Expires 属性来设定浏览器缓存时间,另外还有 Etags 和 opcode 的缓存,根据具体情况进行选择吧

  3.  

减少DNS查找


DNS用于映射主机名和IP地址,一般一次解析需要20~120毫秒。浏览器会首先根据页面的主机名进行域名解析,在有ISP返回结果之前页面不会加载任何内容,所以减少DNS查找可以有效降低等待时间。为达到更高的性能,DNS解析通常被多级别地缓存,如由ISP或局域网维护的caching server,本地机器操作系统的缓存(如windows上的DNS Client Service),浏览器。IE的缺省DNS缓存时间为30分钟,Firefox的缺省缓冲时间是1分钟。 我们能做的是尽量减少一个页面的主机名,但要在浏览器最大并行下载数跟dns查找之间做权衡。根据雅虎的研究,最好将主机名控制在2-4个内。

CDN加速


CDN 的本质也属于缓存,内容分发网络,把数据缓存在里用户近的地方,使用户尽快的获取数据。
CDN 通常是部署在网络运营商的机房,这些运营商为用户提供网络服务,因此用户请求的路由会优先到达 CDN 服务器,如果存在请求的资源的话,就直接返回,以最短路径返回响应,提高了用户访问速度,同时还能够为中心机房减轻压力。其原理如下:

CDN 一般用来缓存静态资源,如css,Script脚本,静态页面,图片等,这些内容修改频率很低但是访问请求频率很高,因此放在 CDN 上能够很好的改善访问速度。

<link rel="preconnect" href="https://cdn.jsdelivr.net">

come from:https://music.liumingye.cn/playlists/598/%E6%B0%91%E8%B0%A3%E6%A6%9C

 

减少重定向


重定向是指将一个URL重新路由到另一个URL。浏览器会自动重定向请求到Location指定的URL上,也就说把之前的过程又重复一遍才能请求到真正的资源,会极大地降低用户体验。

 

参考:(www.cnblogs.com/dojo-lzz/p/…]
( seanlook.com/2015/01/07/…]
( segmentfault.com/a/119000000…]

webpagetest.org

权威又免费的在线网站速度测试 webpagetest.org