写在开头
--这篇bigpipe的笔记早在一年前就想写了,但是一直被耽搁了。终于今天再翻看旧ppt时才想起要补上这篇博客。
本文中关于bigpipe的介绍是根据网络上的资料整理出来的(图片均来源于网络),而实现部分是博主的亲身实践。
1.什么是bigpipe
搞互联网的同学也许都知道一个数字——4秒,有研究表明,如果一个网站没有在4秒之内加载完成,用户就会感到焦躁不愉快,并离开这个网站(数据来自性能测试网站http://gtmetrix.com/)。
2010 年初的时候,Facebook 的前端性能研究小组开始了他们的优化项目,经过了六个月的努力,成功的将个人空间主页面加载耗时由原来的5 秒减少为现在的2.5 秒。这是一个非常了不起的成就,也给用户来带来了很好的体验。在优化项目中,工程师提出了一种新的页面加载技术,称之为Bigpipe。
举个例子介绍bigpipe(借张图来解释):
在饭馆点菜吃的时候,如果点了四个菜,传统的网页加载模式是把所有菜都炒好了再上桌。当用户吃上菜的时候,已经是第5s了。而运用bigpipe输出页面,是炒一个就上一个菜,用户可以先吃着,厨师再炒第二个菜。甚至可以几个菜并发同时炒。所以用户吃上第一口菜的时间可以是第1s,比传统的提前了很多。
2.Bigpipe思想与原理
BigPipe提出分块的概念,即根据页面内容位置的不同,将整个页面分成不同的块儿– 称为pagelet。该技术的设计者Changhao Jiang 是研究电子电路的博士,可能从微机上得到了启发,将众多pagelet加载的不同阶段像流水线一样在浏览器和服务器上执行,这样就做到了浏览器和服务器的并行化,从而达到重叠服务器端运行时间和浏览器端运行时间的目的。使用BigPipe 不仅可以节省时间,使加载的时间缩短,而且可以同过pagelet的分步输出,使一部分的页面内容更快的输出,从而获得更好的用户体验。
FaceBook的页面被分成了很多不同的pagelets,如图:
页面加载时间消耗图:
bigpipe流水线式加载页面图:
3.Bigpipe与传统页面渲染、ajax区别
3.1 传统页面处理过程
3.2 Ajax模块化处理过程
3.3 Bigpipe处理过程
3.4 页面加载时间对比
传统模式(BP关闭):
流水线模式(BP开启):
页面等待服务器输出的时间从248ms 降到了 70 ms,也就是说最快70ms后就可以显示部分页面效果了。
4.Bigpipe优点和适用场景
Bigpipe好处
- 使页面分段输出,加快了页面显示,改善用户体验
- 使页面模块化,更加便于维护
- 每个pagelet使相互独立的,单个pagelet加载失败不会影响整个页面的显示
- Pagelet的输出顺序可以开发人员自由控制,可以尽早的输出用户关心的模块
Bigpipe适用场景
- 第一个请求时间较长,后端程序需要多次查询数据
- 页面上的动态内容可以划分在多个区块内显示
5.Bigpipe实现
(1)输出示例
传统模式:
<html> <div id="pl_main">主要内容</div> </html>
Bigpipe模式:
<html> <script scr="bigpipe.js"/> <div id="bigpipe_15" pageletName="pl_main">待替换内容</div> </html> <script>bigpipe.onPageletArrive({ "dependScripts":[], "dependStyles":[], "pageletId":"15", "pageletName":"pl_main", "htmlContent":"主要内容" }); </script>
(2)Bigpipe实现--前端任务
- JS/CSS拆分
- JS/CSS加载卸载
(3)Bigpipe实现--后端任务
3.1 管理和组织Pagelets--
利用配置表/数据库管理树状结构的Pagelet(一个页面可以由1个或多个pagelet树组合而成)
eg :新浪微博pagelets结构
3.2 管理Pagelet资源依赖
利用配置表/数据库管理依赖的js和css
3.3 设计一个action/controller/servlet,将url返回的html包装成脚本格式
eg:
原动态请求url: http://test.xxx.com/test/222.html
包装后的请求url: http://test.xxx.com/bigpipe/${pageletName}.pagelet , 新页面的返回如下:
<script>${param.bigpipeCallback}({ "dependScripts":[], "dependStyles":[], "pageletId":"15", "pageletName":"pl_main", "htmlContent":"${/test/222.html返回的html内容,注意需要对单/双引号做转义!}" }); </script>
3.4 分段输出Pagelet
利用HTTP1.1特性,实现分段输出: Transger-Encoding:chunked
输出模式:
- Traditional模式(传统模式,不分段,一次性输出整个页面)
- Streamline模式(分段输出,先输出页面框架和pagelet占位div,然后根据树状结构,逐个输出脚本格式的pagelet)
- SmartStreamline模式(优化过的Streamline模式,不同点是先输出页面框架和第一个pagelet)
- AutoAgent模式(根据UserAgent的内容自动选择输出模式,可用来针对spider/robot选择传统模式输出)
3.5 自定义bigpipe标签
下面是一个使用自定义标签,将2个pagelet组织成一个jsp页面的例子:
<html> <script type="text/javascript" scr="bigpipe.js"/> <body> <bigpipe:page pageName="xxxx" renderMode="autoStreamline"> <bigpipe:pagelet pageletName="pagelet1"> <bigpipe:param name="userId">123</bigpipe:param> </bigpipe:pagelet> <bigpipe:pagelet pageletName="pagelet2"> <bigpipe:param name="type">111</bigpipe:param> </bigpipe:pagelet> </bigpipe:page> </body> </html>
6.引用与参考资料
1).新浪微博的BigPipe后端实现技术分享
2).使用BigPipe提升浏览速度—— 流水线技术在新浪微博的实践
3).从新浪微博改版谈网页重构——bigpipe中的页面构建优化
4).Facebook创新之BigPipe:优化页面加载时间 http://www.infoq.com/cn/news/2010/08/bigpipe-facebook-optimize
5).淘宝 BigPipe学习研究:http://www.searchtb.com/2011/04/an-introduction-to-bigpipe.html
6).bigpipe的java实现:http://codemonkeyism.com/facebook-bigpipe-java/