[关闭]
@mircode 2016-07-14T15:34:38.000000Z 字数 4188 阅读 1857

Pagelet的前世今生

BigPipe BigRender LazyRender Quickling PageCache


一、序言

试想这样一个场景,一个经常访问的网站,每次打开它的 页面都要要花费6 秒;同时另外一个网站提供了相似的服务,但响应时间只需3秒,那么你会如何选择呢?数据表明,如果用户打开一个网站,等待3~4秒还没有任何反应,他们会变得急躁,焦虑,抱怨,甚至关闭网页并且不再访问,这是非常糟糕的情况。所以,网页加载的速度十分重要,尤其对于拥有遍布全球的 5亿用户的Facebook(全球最大的社交服务网站)这样的大型网站,有着大量并发请求、海量数据等客观情况,速度就成了必须攻克的难题之一。


二、BigPipe 高性能的“流水线技术”

2010年初的时候,Facebook的前端性能研究小组开始了他们的优化项目,经过了六个月的努力,成功的将个人空间主页面加载耗时由原来的5秒减少为现在的2.5秒。这是一个非常了不起的成就,也给用户来带来了很好的体验。在优化项目中,工程师提出了一种新的页面加载技术,称之为Bigpipe。

1、BigPipe原理

传统模型

传统的页面展示模式,相当于去餐馆吃饭,选好桌子点好菜,然后单子下厨房,大厨开始做菜,所有菜都做好了之后,才给端上来吃。

堵塞式模型

BigPipe模型

BigPipe相当于在餐馆吃饭,先选好桌子点好菜(确定用户布局和要展现的模块),单子下到厨房后,多个大厨就可以同时上阵(服务端并发),做好一样端上来一样吃一样(客户端并发)。
流式模型

原理图
流式模型

综述

通过对比两种模型,我们可以发现BigPipe方式,可以最大效率的利用CPU并行的特点,加快页面的渲染。服务器通过将页面分块,同时采用多线程的方式并行执行SQL生产数据块复用HTTP请求通道多次向浏览器Flush数据。最终的效果可以做到浏览器边下载边渲染,而不是一直等待服务端页面生成完毕之后,再进行渲染。大大提升了页面的响应时间。

同一个页面,传统模式的时间约为[Sql1+Sql2+Sql3+Sql4+Sql5]+网络传输时间+浏览器渲染时间。采用BigPipe的方式的话,时间约为Max(Sql1,Sql2,Sql3,Sql4,Sql5)+网络时间+浏览器渲染时间

2、BigPipe实践

技术点:长连接+多次truck,后端多线程flush数据块。

生成主体框架

首先,我们需要将页面分块。第一块,为整个页面切分的框架。如:
将页面分块

  1. <html>
  2. <head>BigPipe</head>
  3. <body>
  4. <div id="pagelet_1"></div>
  5. <div id="pagelet_2"></div>
  6. <div id="pagelet_3"></div>
  7. <div id="pagelet_4"></div>
  8. </body>

注意:整个框架级别的分块,是一个不闭合的结构,因为如果闭合的话,那么浏览器就会关闭和服务器端的链接。

生成Pagelet页面切片

之后,服务器端并行生成Pagelet内容。如:

  1. // Pagelet1
  2. BigPipe.onPageletArrive(
  3. {
  4. id:"pagelet_1", // 目标DIV的ID
  5. content:"<p>我是pagelet_1</p>", // 需要填充的HTML片段
  6. css:["common.css","pagelet_1.css"],// 依赖的CSS
  7. js:["common.js","pagelet_1.js"], // 依赖的JS
  8. ....
  9. }
  10. );
  11. // Pagelet2
  12. .......
  13. // Pagelet3
  14. .......

注意: Pagelet中通常包含,PHP生成的HTML片段,Pagelet依赖的JS和CSS,以及页面框架中DIV的ID

当切分的页面的每一块后台逻辑执行完毕之后,都会向页面返回一个Pagelet。然后,由JS将内容依次填充到对应Pagelet中。

  1. <div id="pagelet_1"></div>
  2. <div id="pagelet_2"></div>
  3. <div id="pagelet_3"></div>
  4. <div id="pagelet_4"></div>
  5. <script>BigPipe.onPageletArrive{...}</script>
  6. <script>BigPipe.onPageletArrive{...}</script>
  7. <script>BigPipe.onPageletArrive{...}</script>
  8. <script>BigPipe.onPageletArrive{...}</script>

实例代码如下

实例代码

3、BigPipe总结

原理示意图

示意图

对比图

示意图
示意图

4、注意

BigPipe先输出页面整体布局,然后逐步输出脚本块,一边输出一边执行,将内容渲染回页面布局中。这样可以让服务端的运算、网络传输和浏览器端的渲染变成并行。BigPipe最主要解决的问题是服务端的运算时间,当服务端的运算时间大于 300 ~ 500ms 时才能体现出优势。当服务端响应非常快(小于 100ms),BigPipe 退化为下面要讲的 BigRender。

5、附件

BigPipe新浪微博实例

三、BigRender减少Dom数,延迟渲染

BigRender属于前端优化的一种手段,通过减少Dom数,加快页面首屏的渲染。这个应该是淘宝率先采用的一种前端优化方案。为什么淘宝没有使用BigPipe呢?看图吧

BigRender

淘宝后端性能优化的已经很快了,通过BigPipe并行计算已经不能提升多少了。所以,采用减少前端的Dom节点数,来加快网页渲染速度。

1、BigRender实现

先看看效果,下面的截图是美团的页面的截图,通过截图可以看出,上面红色框内的就是首屏的内容,这部分是被渲染好的,下面蓝色框内的只是输出了个占位框,内容时空白的,内容都被保存在一个隐藏的TextArea框内(也可以隐藏到注释等其他内容中,只要不增加Dom节点数量就可以)。当鼠标滑动到下屏幕的时候,开始填充空白区域的内容。

美团首屏

代码如下:

  1. <!--目标容器-->
  2. <article class="br-warp"></article>
  3. <!--通过隐藏HTML内容,减少DOM节点数-->
  4. <textarea class="br-rendered" style="display:none">
  5. article中包含的HTML代码,因为textareadisplaynone的元素,
  6. 所以浏览器不会渲染textarea。当滚动屏幕时,通过JStext区域内
  7. 容,加载到article中。
  8. </textarea>
  9. <!--通过JS将隐藏的内容,填充的目标容器中-->
  10. <script>
  11. $("article").html($('textarea').html());
  12. </script>

看看Her里面是怎么处理的

美团首屏

2、附件

淘宝详情页的BigRender优化与存放大块HTML内容的最佳方式
美团首屏BigRender优化

四、LazyRender 延迟加载

延迟加载和BigRender类似,只不过需要填充的代码是通过Ajax向后端动态请求回来的并没有将代码隐藏到页面中。这种模式多用于移动端。分段加载可以节省流量,加快页面的响应速度。当用户下滑手机屏幕时候,再动态的发送Ajax去请求所需的页面,尤其是网速交差的情况,使用分段加载,可以很大成度提升用户体验。

  1. <html>
  2. ...
  3. <div>首屏代码</div>
  4. <!--加载第二屏内容-->
  5. <script>lazyrender('second');</script>
  6. ...
  7. </html>

五、Quickling 变形的"Ajax"

Facebook提出了一个新名词Ajaxify,顾名思义,就是将传统的POST/GET转换为Ajax请求。优点显而易见,首先减少了不必要的HTML传输,只请求和渲染页面需要更新的部分,这就相应减少了所需传输的内容加快了内容送达至用户的时间。并且也减少了服务端对HTML的不必要的渲染。Facebook也提到了可以减少session的重复load/unload。

1、Quickling概述

将连接通过Ajax形式进行改造
hao123

还有最典型的tab签切换
tab

2、解决SEO问题

使用Ajax也许不是什么新鲜的新闻,大家拒绝这项技术的原因可能很大程度基于SEO的需求。从网上摘录了这么一段解决方案,如:

  1. // 请求参数key
  2. $isAjax = $_GET["key"];
  3. $con = include 'content.php';
  4. // 如果是ajax请求,返回页面片段
  5. if($isAjax == "ajax"){
  6. echo $con;
  7. // 如果不是ajax请求,则返回完整页面
  8. }else{
  9. $head = include 'head.php';
  10. $foot = include 'head.php';
  11. echo $head + $con + $foot;
  12. }

3、附录

Quickling实现原理
FaceBook性能优化

六、PageCache 页面缓存

这个就是将经常访问的页面放到缓存中,加快前端的响应速度。这个一般会在后端优化,这里就不在多说了。

七、总结

八、应用

看一下FIS+的官网,我们可以发现FIS+针对以上几种性能优化都做了封装。

tab

对照Her的架构图,我们也就很容易理解他的架构了。

her

参见

新能优化

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注