前端界面是用户与计算机交互的一个媒介,为用户提供更好的交互体验,首先需要从明白计算机和网络都干了什么,然后才能针对性的作出一些优化。
本文将从web页面请求历程为例,聊聊输入url到用户看到页面整个过程背后都发生了什么。文章主要参考了《大型网站性能优化实战》以及《高性能网站建设指南》这两本书,同时也参考了网上很多优秀的文章,下面就让我们开始吧~
从用户打开浏览器,浏览网页的感知出发,以下几点因素是衡量用户性能方面对用户体验造成比较重要影响的
在这些因素中,最基础的就是白屏时间。先明确一个问题,在用户输入url之后,浏览器发送请求到服务器,从服务器获取一些资源,将资源渲染完成后,用户就能在浏览器里看到完整的web界面。在渲染完成之前,页面展示出来的结果就是白屏(有人可能会说有的界面会出现loading或者骨架屏之类的,那些资源也是从服务器获取的,这只是一个界面优化的方式,在界面完全渲染出来之前,让用户不至于一直看着空白的屏幕)。
(图片取自《大型网站性能优化实战一书》)
大概的步骤如下:
对于前端而言,第四个步骤可发挥的余地比较大。前端性能有个黄金法则:只有10%-20%的最终用户响应时间花在了下载HTML文档上,其余的80%-90%时间花在了下载页面中的所有组件上,在进行前端性能优化的时候,可以根据这个黄金法则进行梳理。
接下来让我们仔细的从这几个步骤出发聊聊吧~
DNS是一个分布式数据库,用于维护URL到其IP地址的映射关系,DNS Lookup是浏览器从DNS服务器中进行域名查询的过程,在一次请求中,首先会进行页面本身的域名查询,在浏览器在解析HTML代码过程中,需要加载JS,CCS,Image等资源的时候也需要进行域名解析。
在DNS查询阶段可进行以下优化:
DNS查询获得IP地址之后,还需要进行ARP(地址解析协议)请求,从而获得对应的MAC地址,之后才能完成通信,ARP以IP地址为线索,定位下一个应该接收数据分包的主机MAC地址。
ARP会维护每个主机和路由器上的APR缓存(或表),缓存中维护着的是每个IP到MAC地址的映射关系,当一个映射关系被缓存过后,下次再向这个地址发送数据时就不需要再次发起ARP请求了,ARP请求通常使用UDP协议(因为需要广播)。
Q:为什么有了IP地址还要加上MAC地址呢?
A:首先TCP/IP是网络层的协议,根据网络的不同同一台机器的ip地址也会发生改变,因此并不能通过IP地址实现与计算机的一一映射,而MAC地址在链路层,与计算机是一一绑定的(出厂的时候就焊死了,是唯一的标识),因此能通过MAC地址实现与计算机的一一映射。其次,仅通过IP地址必须通过在局域网内广播才能与主机匹配,如果只采用IP定位,就会造成网络上大量的广播包,形成广播风暴,大大浪费网络带宽和资源。若采用IP和MAC地址则能确定主机位置,只需要第一次通信广播将IP和MAC相互映射,之后都是通过单播通信。
浏览器获取到目标地址的IP地址之后,就能获取到对应的端口号(http默认80,https默认443),接着进行对应的数据包封装,包封装好之后会进行TCP请求,这就是很熟悉的TCP/IP三次握手,简单的描述一下三次握手如下(只是便于记忆,详细的可以参考专门的博文):
建立好连接之后,就开始进行TCP传输,在服务器端,可以通过优化来降低响应响应给客户端的网络耗时。TCP传输是分段的,一个HTTP响应报文会被操作系统切成多个MSS大小(一般为1460B),发送端每次只会按顺序发送若干段,通过拥塞窗口和接收端窗口,知道接收端接收到完整的报文为止。报文越大,受拥塞控制算法的影响也越大。
接收端流量控制用的是滑动窗口机制,本质上是描述接收方的TCP数据报缓冲区大小的数据,通过这个窗口大小,TCP可以慢慢从数据的左边移到数据的左边,从而实现按顺序进行分段数据的发送。(知道一次能接收多少所以这边才能一次传多少过去)
发送端流量控制用的是拥塞窗口机制,拥塞窗口的原理:TCP发送方先发送少量的数据报文段,然后等待对方的回应,ACK回应后就把这个窗口的大小加倍,然后连续发送两个数据包,对方回应后,继续加倍,知道发生错误或丢包,这样就能检测到网络的承载能力,从而按这个大小发送数据,这个阶段的优化可以通过减小HTTP报文大小和HTTP头的大小来实现,因为报文越小,传输所需要的RTT次数越少,耗时越短(AJax异步化可以减少这个问题)
在传输阶段可进行以下优化:
传输结束之后要记得关闭TCP连接,这里简单描述一下(具体的看专业的分析博):
浏览器会向服务器发起请求,在HTTP中,请求方法包括简单请求和非简单请求:
除请求内容之外,HTTP请求还包括很多信息,这些信息都被放在头部,一起带给服务器
HTTP是基于TCP协议的,除了HTTP请求之外,根据业务需求,还会有ws请求,ftp请求等。
这里插播一个http协议的比较
http1.0,http1.1,https以及http2.0
http协议最初的目的只是将HTML文档从web服务器传送到客户端的浏览器,但是我们的页面月来越复杂,网络情况也更加复杂,所以HTTP也在不断的优化中
http1.0和http1.1
https
https需要到CA申请证书,运行在SSL/TLS上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的,默认的端口是443,它可以有效的防止运营商劫持,解决了防劫持的一个大问题
https的流程:
Q:为何使用对称加密和非对称加密混合的方式?
A:在这个流程中可以看出,https对数据加密使用的是对称加密,对称加密的密钥是通过非对称加密传输的,这样保证了密钥传输过程中的安全,理论上而言非对称加密会比对称加密安全,但是由于非对称加密会比较耗时,所以为了加快传输速度,在真正数据传输的时候用的对称加密
http2.0
http2.0与http1.x相比的新特性:
这个过程主要工作是服务器端处理数据,返回数据,主要的性能优化点在降低服务端RT(Response Time)上。服务器端返回的响应包含请求的网页以及状态码,压缩类型,如何缓存页面,还有需要设置的cookie信息,隐私信息等待。
服务端请求处理响应主要包括以下几个步骤:
对于HTTP请求而言,HTTP状态码是请求状态的体现,常见的状态码如下:
1**:服务器收到请求,需要请求者继续执行操作
101:需要切换协议,表示服务器应客户端升级协议的请求对协议进行切换,就像http访问https的时候
2**:操作被成功接受并处理
200:成功
204:操作成功但是没有任何的返回
3**:重定向,需要进一步的操作以完成请求
301:请求的资源被永久移动到新url里面,在nginx上配置rewrite ^/(.*)$ http://**** permanent;
可实现
302:暂时的重定向,跳转后会保留旧地址,在nginx上配置rewrite ^/(.*)$ http://**** redirect;
可实现
304:客户端的缓存,比如之前的图片,二次加载的时候可能就会有304,避免重新加载
插播一个知识点:浏览器缓存
因为304的出现和缓存密不可分,所以在这里讲一讲浏览器的缓存。
浏览器的缓存是指在上一次访问的时候本地备份保存,下一次使用浏览器就可以直接加载本地资源,这样降低请求次数,减少网络延迟,加快页面打开速度。
浏览器缓存分为强缓存和协商缓存
强缓存(Expires和Cache-control)
强缓存是利用http头的Expires(http1.0)和Cache-control(http1.1)两个字段进行控制的
协商缓存
协商缓存会先发送请求到服务器,和服务器商量商量是用本地还是服务器返回,如果本地生效,返回304状态码
4**:客户端错误,因为某种原因导致无法完成请求
401:请求要求用户的身份认证,一般是账号密码不对
403:服务器理解请求客户端的请求,但是拒绝执行此请求,一般是账号密码对了但是这个账号密码没有对应权限
405:请求方法错了,比如前端写的get,但是后端接口写的是post
429:请求次数过多,比如某个请求在几秒内触发了上百次
5**:服务器错误,服务器在处理请求过程中发生了某些错误
500:服务器内部错误
502:充当网关或代理的服务器,从远端服务器接收到了一个无效的请求
504:网关超时
在服务器端,每一步都有可优化的地方,对中小型网站而言,重心可能会放在数据获取过程的优化上,对大型网站而言,每一步的优化都可能带来质的提升。
最后一步是浏览器的渲染,这部分内容比较多,大体的过程如下:
在此,输入url之后到页面渲染的全部过程就大概聊完了,浏览器渲染过程比较复杂,将在单独开一篇进行阐述~