1.技术背景

  动态web网站的历史可以追溯到万维网初期,相比于静态网站,动态网站提供了强大的可交互功能.经过几十年的发展,动态网站在互动性和页面显示效果上有了很大的提升,但是对于网站动态网站的整体页面加载架构没有做太大的改变.对于用户而言,页面的加载速度极大的影响着用户体验感.与静态网站不同,除了页面的传输加载时间外,动态网站还需考虑服务端数据的处理时间.像facebook这样大型的用户社交网站,必须考虑用户访问速度问题,

  传统web模式采用了顺序处理的流程来处理用户请求.即用户向客户端发送一个请求后,服务器处理请求,加载数据并渲染页面;最后将页面返回给客户端.整个过程是串行执行的,具体流程如下:

  1. 浏览器发送一个HTTP请求到Web服务器。
  2. Web服务器解析请求,然后读取数据存储层,制定一个HTML文件,并用一个HTTP响应把它发送到客户端。
  3. HTTP响应通过互联网传送到浏览器。
  4. 浏览器解析Web服务器的响应,使用HTML文件构建了一个的DOM树,并且下载引用的CSS和JavaScript文件。
  5. CSS资源下载后,浏览器解析它们,并将它们应用到DOM树。
  6. JavaScript资源下载后,浏览器解析并执行它们。

  整个流程按必须顺序执行,不能重叠,这也是为什么传统模式随着网络速度的提升访问速度没有很大提升的原因.解决顺序执行的速度问题,一般能想到的就是多线程并发执行.Facebook 的前端性能研究小组采用浏览器和服务端并发执行的思路,经过了六个月的努力,开发出了BigPipe页面异步加载技术,成功的将个人空间主页面加载耗时由原来的5 秒减少为现在的2.5 秒。这就是我们本文要介绍的高性能页面加载技术---BigPipe.

2.BigPipe设计原理

  BigPipe的主要思想是实现浏览器和服务器的并发执行,实现页面的异步加载从而提高页面加载速度.为了达到这个目的,BigPipe首先根据页面的功能或位置将一个页面分成若干模块(模块称作pagelet),并对这几个模块进行标识.举个例子,在博客园个人首页包括几大板块,如头部信息,左边信息,博文列表,footer等.我们可以将首页按这些功能分块,并用唯一id或名称标识pagelet.客户端向服务端发送请求后(发出一次访问请求,如请求访问个人博客首页),服务端采用并发形式获取各个pagelet的数据并渲染pagelet的页面效果.一旦某个pagelet页面渲染完成则立刻采用json形式将该pagelet页面显示结果返回给客户端.客户端浏览器会根据pagelet的id或标识符,在页面的制定区域对pagelet进行转载渲染.客户端的模块加载采用js技术.具体流程如下:

   1. 请求解析:Web服务器解析和完整性检查的HTTP请求。
   2. 数据获取:Web服务器从存储层获取数据。
   3. 标记生成:Web服务器生成的响应的HTML标记。
   4. 网络传输:响应从Web服务器传送到浏览器。
   5. CSS的下载:浏览器下载网页的CSS的要求。
   6. DOM树结构和CSS样式:浏览器构造的DOM文档树,然后应用它的CSS规则。
   7. JavaScript中下载:浏览器下载网页中JavaScript引用的资源。
   8. JavaScript执行:浏览器的网页执行JavaScript代码

  前三个阶段由Web服务器执行,最后四个阶段(5,6,7,8)是由浏览器执行。所以在服务器可以采用多线程并发方式对每个pagelet进行数据获取和标记生成页面,生成好的pagelet页面发送给前端.同时在浏览器端,对css,js的下载可以采用并行化处理.这就达到了浏览器和服务器的并发执行的效果,这样使得多个流程可以叠加执行,加少了整体页面的加载时间.浏览器端的并行化交给浏览器自己处理不需要我们做额外工作.在BigPipe中主要是处理服务端的并行性.

3. BigPipe的实现原理

  在BigPipe,一个用户请求的生命周期是这样的:在浏览器发送一个HTTP请求到Web服务器。在收到的HTTP请求,并在上面进行一些全面的检查, 网站服务器立即发回一个未关闭的HTML文件,其中包括一个HTML 标签和标签的开始标签。标签包括BigPipe的JavaScript库来解析Pagelet以后收到的答复。在标签,有一个模板,它指定了页面的逻辑结构和Pagelets占位符。例如:

 1 <html>
 2 <head>
 3     <title>struts2-bigpipe-plugin</title>
 4     <script type="application/javascript">
 5            function replace(id, content) {
 6                  var pagelet = document.getElementById(id);
 7                  pagelet.innerHTML = content;
 8            }
 9     </script>
10 </head>
11 <body>
12 <table width="100%">
13     <tr border="1">
14         <td width="50%" bgcolor="#f0f8ff"><div id="one">${one}</div></td>
15         <td width="50%" bgcolor="#faebd7"><div id="two">${two}</div></td>
16     </tr>
17     <tr>
18         <td width="50%" bgcolor="#7fffd4"><div id="three">${three}</div></td>
19         <td width="50%" bgcolor="#8a2be2"><div id="four">${four}</div></td>
20     </tr>
21 </table>
View Code

相关文章:

  • 2021-12-24
  • 2021-11-10
  • 2022-01-30
  • 2021-07-14
  • 2022-02-02
  • 2021-10-30
  • 2021-05-17
  • 2021-12-28
猜你喜欢
  • 2022-12-23
  • 2021-11-19
  • 2022-01-07
  • 2022-12-23
  • 2021-09-26
  • 2021-04-03
  • 2021-09-01
相关资源
相似解决方案