Web前端不少优化原则都是从如何提高网络通信效率的角度提出的,可是这些原则使用的时候仍是有不少陷阱在里面,若是咱们不能深刻理解这些优化原则背后所隐藏的技术原理,颇有可能掉进这些陷阱里,最终没有达到最佳的预期效果,今天我在这里分析下浏览器和服务端通信的一些细节问题,但愿经过分析这些细节问题,能给你们一个启迪,能更好的理解这些优化原则背后的隐秘,最终能更好的运用这些原则。javascript
网站的通信技术是构建在http协议上,http协议底层通信手段使用的是tcp/ip协议,可是tcp通信协议在创建链接和断开链接这两个动做上是很是消耗通信性能的,这主要是由于tcp/ip协议在链接创建时候的三次握手机制和断开链接时候的四次挥手机制所致,咱们来看看下面的图形:css
图中中间被红色标记的方块就是tcp/ip协议在创建链接时候须要发送三次报文才能确认链接是否创建成功,中间四个蓝色的方框就是说明tcp/ip协议在断开链接时候要发四次报文才能肯定链接最终被断开,而一个具体的http请求和响应也就发送两次报文,这也就说明若是浏览器每次和服务端的交互都要新建和关闭一个tcp/ip链接,那么浏览器和服务器之间就要往返9次报文通信,而真正用来处理用户请求的报文确只有其中的两次,换句话说这样的一个请求大概会有80%左右的性能都不是用来处理业务需求,等因而损失了80%左右的性能,固然这个比率是9次报文交互的数据大小一致状况下得出的,若是用户业务请求和响应的数据量比较大,那么创建链接和断开链接的性能损失占比会下降,不过就算占比下降了那也是在请求处理自己的时间变的更慢的基础上的下降,要是浏览器和服务器之间的距离特别大,那么多出来的7次报文交换的效率问题就更加严重了,无论怎样,tcp/ip的三次握手机制和四次挥手机制只要发生都会对网络请求效率产生重大影响。html
为了解决这个报文交互次数过多的问题,http协议自己也发生了改变,那就是http开始采用了长链接,使用长链接后网站只须要开启一个长链接,在用户关闭浏览器关闭以前浏览器里的网页都会复用这个长链接。不过http协议的1.0版本默认是不启用长链接的,因此在使用http协议1.0版本时候我就得手动的打开长链接,这个方法就是在http头里设置Connection: Keep-Alive,而http1.1版本里长链接是默认打开的,因此不须要咱们手动的设置,并且时下的浏览器几乎都支持http1.1协议,所以大多时候状况下咱们是没有必要手动去打开长链接的。前端
虽然http协议采用长链接后能够减小网站通信时候三次握手和四次挥手的次数,可是长链接创建起来后须要浏览器和服务器长时间维护,这自己会消耗浏览器和服务器的性能,特别是服务器端长时间维护长链接自己还会损坏服务器处理并发的能力,因此早期浏览器会限制http1.1开启链接的数量,例如ie7这个古董浏览器,它准许http1.1最多开启2个长链接,而http1.0由于默认使用短链接它默承认以开启4个,下面有张图能够说明,以下所示:java
提高浏览器加载效率的手段除了提高每一个链接的传输效率外,其实还有一种方式,这个方式就是使用多个链接进行并行加载,这个等于几我的联合起来一块儿完成一个任务,那么效率确定就比一我的高,而页面加载时候很符合使用并发加载的场景,例如咱们让页面里的图片并行加载确定会比一个个加载图片的效率要高多了。回到浏览器支持的链接数的问题,因为早期浏览器在http1.0和http1.1链接数的差别,某些网站例如维基百科这样的网站,它的静态资源特别多,为了充分发挥并发的优点,它将存放这些静态资源的服务器采用http1.0协议,这样就能并行加载更多的静态资源,由于这个并行加载的整体效率提高相比tcp/ip握手和挥手的损失要高的多,不过如今这个手法已经起不到什么做用了,由于新版的浏览器已经把两种版本的http协议支持的链接数调整一致了,由于长链接能够复用链路,所以使用长链接的效率会比非长链接更好。web
上面链接数也是有一个限制的,这个限制就是必须是在同一个域名下,若是一个页面某些静态资源放在不一样域名下面,那么这个作法就能够增长页面里的并发数量,例如咱们把一些不是常常变化的静态资源例如图片、外部的css文件以及javascript文件单独放置在一个静态资源服务器上,静态资源服务器对外的url地址和页面自己的url地址不在同一个域名下,那么页面自己的并发加载链接数就会增长一倍,不过这也就意味着浏览器端要维护的长链接数会变得更多,雅虎工程师曾经总结过一个页面里合理的域名数量,那就是两个,这个结论的提出已通过去了好多年了,如今的浏览器和服务器的性能已经今非昔比了,这个跨域数量应该能够增长点,不过我我的认为一个页面的里包含的域名数量仍是不要太多,其实若是咱们web前端优化手段使用得当,两个不一样域名就足够用了,多了价值不大,除非你网站状况是在特殊,例如你看看如今浏览器自己支持的链接数量已经很高了,大部分都是6,ie9甚至还达到了10,翻个倍就有12和20个链接数,咱们在翻个倍就是24和40个,这个数字看起来就很恐怖了,一个计算机支持这么多并发,假如你在浏览器还打开个网站也是这么干的,那么浏览器的并发数多的实在太吓人了,我估计到时计算机自己就跑不动了,因此10多个链接数很够用了,你合理发挥下这些链接数网站的性能就能有很大提高,再说了一个网站并发链接数太多那自己就说明了你在减小http个数这个手段没有运用好。ajax
回到web前端优化的手段,咱们若是把这些手段再仔细分析下就会发现不少手段使用都是在同步请求这个场景下进行了,固然这些手段在合适状况下也能做用于异步加载场景,可是异步加载场景发生并发加载以前须要一个单线程的异步加载,这个单线程的异步加载就和分布式系统里的单点故障有点像了,它颇有多是整个流程的软肋所在,因此合理使用同步请求还能让异步操做性能更加优秀作好准备。上面我讲到浏览器在同一个域名下最多能够开启多少个链接数,可是从事web前端开发的人都能感受到,咱们作页面开发时候实际上是无法控制这个链接数的,那么问题来了,这么多链接究竟是在什么条件下被开启的呢?这个问题很是有意思的,咱们来看下面的瀑布图:跨域
从上面的瀑布图咱们发现,并行下载的是图片,这个推而广之要是咱们看见某些网站的网页作过并发优化处理的设计,咱们就会发现并发的资源都是纯静态的资源,那么这个并发链接数跟咱们页面的设计存在一个怎样的关系呢?首先咱们总结一下页面里的静态资源,在页面里静态资源有html,若是html里面有内联的css代码和javascript代码,那么这些代码也会归属于html,除了html外还有外部的css文件、外部的javascript文件和页面里使用到的图片,那么这些要素怎样会促发页面的并行加载了,换个说法这些要素又是如何促使浏览器同时打开更多链接呢?浏览器
首先咱们要明确一个问题,浏览器之因此能够打开更多链接数,让这么多链接并行执行是有个前提的,这个前提就是这些资源是否是被并行加载的,例如像外部css文件,图片这样的资源,这些资源下载完毕后立刻就可使用,由于它们下载完毕后没有逻辑性问题要处理所以下载完毕后就能够直接拿来使用,所以它们并行加载不会影响到页面的展现问题,这个状况若是碰到javascript就有点麻烦了,外部javascript代码是包含逻辑在里面,并且有些逻辑颇有可能会影响页面的展现,因此javascript下载完毕后,浏览器就得立刻执行,因此咱们就会看到这样的瀑布图,以下图所示:服务器
上面的空白区就是浏览器在执行javascript代码所要花费的时间。浏览器开启多少个链接是浏览器自发的行为,这个自发行为主要出于提高浏览器并发下载效率的角度出发的。因为如今浏览器的链接基本都是采起的是http1.1协议,也就是使用的长链接,那么链接创建后这个链接就会长期维护,若是这个长链接是单独的静态资源服务器上的长链接,这个问题倒没什么,若是这个长链接放在主域名下面,问题就来了,主域名在页面初始化加载时候会用来下载html,若是咱们为提升并发下载效率,让这个主域名下还放置其余的静态资源,那么可能会致使浏览器和主域名的服务器下维护更多的长链接,而页面后续操做基本是使用ajax来操做的,而ajax每每只会复用其中一个长链接,那么其余多余的长链接等于要空转了,这个空转还须要消耗浏览器和服务器的系统资源,因此咱们发现主域名下的请求资源类型必定要认真加以控制,能迁移到单独的静态资源服务器上的必定要进行迁移,尽可能让主域名下处理的请求都是包含业务逻辑的请求,这样就能够有效提高系统资源的使用率。这个问题进一步思考下去,咱们就会发现若是服务端的业务应用服务器以前放置一个反向代理,反向代理都是使用静态资源服务器,而静态资源服务器对并发的承载能力是远超业务应用服务器,若是主域名下咱们不当心放置了太多静态资源,要是后台使用了反向代理,那么反向代理也能够减轻这种长链接所形成的计算资源损失。
上面这些场景都是在浏览器同步请求下进行了,那么换到异步请求这个并行加载静态资源的手段还有效吗?回答这个问题前,咱们首先要想一想异步加载会致使新的静态资源被加载吗?这个固然可能,特别是在前端MVC的场景下,咱们会把模板技术放到浏览器端完成,这个时候有些html模板一开始可能会包含在javascript代码里,做为一个变量存储下来,而这个模板里颇有可能包含好多新的图片被使用,当ajax从服务端获取数据后,解析了这个模板,而后咱们把构造好的模板加入到页面的DOM结构里,浏览器从新渲染页面时候看到不少新图片须要加载,就有可能会开启多个链接进行并行加载来提高资源加载效率,若是碰到经过ajax技术动态加载外部CSS文件,那么这个并行加载状况就会更加突出了,由于css文件里颇有可能包含大量的图片资源,若是咱们把不变的静态资源都放置在了单独的静态资源服务器,那么这个并行加载就不会在主域名下打开更多长链接,因而可知,将静态资源使用单独的域名的静态资源服务器处理的好处很是之多。
如今http2.0协议还在起草之中,http2.0若是落地将会给web前端优化技术产生重大影响,http2.0打算在一个页面里只使用一个tcp/Ip链接,不过http2.0会在这个链接上进行链路复用,也就是让一个链接上也能作到并行操做,让链接的利用率更高,若是http2.0落地后,web前端里那些用于减小http链接数的手段都会失去市场了,由于协议自己就能处理好并发的问题了,到时像外部css文件,外部javascript文件,css sprite技术说不定就要成为历史了。
看来本主题又写不完了,下篇接着写吧,今天是元宵节,这里我祝你们节日快乐。