网站速度是Facebook的重要目标,2009年,Facebook成功的使网站快了两倍,工程师团队为此做了多项创新,BigPipe就是其中的一个秘密武器


BigPipe重新设计了动态网页服务体系,大体思路是:把网页分解成多个小块,叫做pagelet,然后在Web服务器和浏览器建立流水线,让这些pagelet工作于不同阶段,充分利用浏览器和服务器的处理能力


相当于把一个页面切分成多个小页面,对每个小页面进行错峰处理


为了理解BigPipe,先看一下传统方式下用户请求的过程


高性能流水线页面技术 BigPipe_java


这个方式效率比较低,从图中可以看到,整个过程是顺序的,当Web服务器正忙生成一个页面,浏览器处于闲置状态,当Web服务器生成完页面,将其发送到浏览器,浏览器则成为性能瓶颈,服务器则帮不上忙


BigPipe如何工作


BigPipe首先分解网页成多个pagelet,每个Pagelet都经过以下几个阶段:


(1)server解析和检查request


(2)server从存储层获取数据


(3)server生成HTML响应


(4)网络传输


(5)CSS下载


(6)构建DOM树和应用CSS样式


(7)JavaScript下载


(8)JavaScript执行


感觉和传统模式下的页面请求过程一样啊,但BigPipe能让多个Pagelet在同一时刻处于不同的阶段



(Facebook主页的pagelet,每个矩形对应一个Pagelet)


该主页包括多个pagelet,相互独立,从用户的角度来看,页面是一块一块逐步呈现的,感觉网页内容呈现得非常快,大大减少了用户对页面延时的感知


例如当“导航pagelet”处于页面显示阶段时,“新闻动态pagelet”可能正处于server生成阶段


在BigPipe中,一个用户请求的生命周期是这样的:


浏览器发送一个HTTP请求到Web服务器,服务器收到请求后,进行一些必要的检查,然后立即返回一个不完整的HTML文件


其中有<head>和<body>


<head>中包括BigPipe的JavaScript库,用来解析Pagelet


<body>中是一个模板,描述了页面的逻辑结构,每个逻辑部分使用pagelet占位符进行占位,例如:


<div>

<div class="left">

<div id="pagelet_nav"></div>

</div>

<div class="main">

<div id="pagelet_composer"></div>

<div id="pagelet_ads"></div>

</div>


Web服务器一个接一个的生成pagelet,只要一个pagelet生成了,立即被发送到客户端,客户端收到一个pagelet后就开始解析并加载CSS,然后渲染显示出来,于此同时,服务器在并行处理下一个pagelet


例如,浏览器可以在下载3个pagelet的CSS的同时,渲染另一个pagelet内容,与此同时,服务器在生成另一个pagelet的内容


高性能流水线页面技术 BigPipe_java_02


所以BigPipe的结果就是:多个pagelet同时执行,但处于不同阶段,使浏览器和服务器并行高效处理


pagelet的内容是一个JSON对象,包括HTML内容,和需要引用的CSS、JavaScript


BigPipe首先下载pagelet的CSS,然后在这个pagelet占位符所在的位置进行显示,多个pagelet的CSS可同时下载,可以无序,JavaScript的优先级最低,所有pagelet都显示出来之后才开始下载JavaScript


性能测试结果


下图是传统模式与BigPipe的性能比较图,对Facebook主页的延迟时间进行了对比,收集数据方式是在禁用浏览器缓存的情况下加载页面50次,该图显示BigPipe使用户在大多数浏览器中感受到的延迟减少了一半


高性能流水线页面技术 BigPipe_java_03