高性能页面加载技术(流水线加载)BigPipe的C#简单实现(附源码)

一,BigPipe简介

    BigPipe是一个重新设计的基础动态网页服务体系。大体思路是,分解网页成叫做Pagelets的小块,然后通过Web服务器浏览器建立管道并管理他们在不同阶段的运行。这是类似于大多数现代微处理器的流水线执行过程:多重指令管线通过不同的处理器执行单元,以达到性能的最佳。虽然BigPipe是对现有的服务网络基础过程的重新设计,但它却不需要改变现有的网络浏览器或服务器,它完全使用PHPJavaScript来实现。(来源百度百科

  BigPipe可以简单理解为:将网页分为若干个块(pagelet),请求到达服务器后先初始化pagelet布局并Response.Write(这时用户能看到网页的大致布局),然后使用多线程并行执每个pagelet 的业务逻辑,每个pagelet线程执行完后立即Response.Write,对于用户来说,他看到的网页是一块块同时或先后呈现出来,和ajax异步加载比较类似。

 

高性能页面加载技术(流水线加载)BigPipe的C#简单实现(附源码)_第1张图片

二,实现思路

 

    1, 前端实现:需要一个js接收服务端输出的HTML,并显示到对应的pagelet中,每个pagelet是一个局部视图(partialView), 代码如下:

   

 1 var PageLet = PageLet || {};
 2 
 3 PageLet = (function () {
 4     var LoadCss = function (css) {
 5         var c = document.createElement("link");
 6         c.setAttribute("type", "text/css");
 7         c.setAttribute("rel", "stylesheet");
 8         c.setAttribute("href", css);
 9         document.getElementsByTagName("head")[0].appendChild(c);
10     }
11     var LoadJs = function (js) {
12         var s = document.createElement("script");
13         s.setAttribute("type", "text/javascript");
14         s.setAttribute("src", js);
15         document.getElementsByTagName("head")[0].appendChild(s);
16     }
17     //PageLet对象公开InitHtml方法,在后台的输出HTML时会带上该方法。
18 
19 var InitHtml = function (json) { $('#' + json.Pid).html(json.Html); LoadCss(json.Css); LoadJs(json.Js); } return { InitHtml: InitHtml } })();

 

  

        2,服务端实现:先初始化页面pagelet布局并输出,然后用多线程并行执行没个pagelet里的业务,执行完后立即输出,这里需要注意的是:输出的HTML代码(partailView)需要做一个JS包裹,只有这样这段HTML代码才能在对应的pagelet显示。代码如下:

HomeController.cs

  1 using MyBigPipe.Common;
  2 using MyBigPipe.Models;
  3 using Newtonsoft.Json;
  4 using System;
  5 using System.Collections.Generic;
  6 using System.Linq;
  7 using System.Threading;
  8 using System.Threading.Tasks;
  9 using System.Web;
 10 using System.Web.Mvc;
 11 
 12 namespace MyBigPipe.Controllers
 13 {
 14     public class HomeController : Controller
 15     {
 16         private static readonly object _sysRoot = new object();
 17 
 18         public void Index()
 19         {
 20             InitHomeHtml();
 21 
 22             Parallel.Invoke(() =>
 23             {
 24                 //模拟操作1秒
 25                 Thread.Sleep(500);
 26                 //头部块
 27                 InitTop();
 28 
 29             }, () =>
 30             {
 31                 Thread.Sleep(500);
 32                 InitLeft();
 33 
 34             }, () =>
 35             {
 36                 Thread.Sleep(1000);
 37                 //右边块
 38                 InitRight();
 39 
 40             }, () =>
 41             {
 42                 Thread.Sleep(1000);
 43                 //底部块
 44                 InitFoot();
 45             });
 46         }
 47 
 48         private void InitTop()
 49         {
 50             ViewBag.Top = "TopTopTopTopTopTopTopTopTopTopTopTopTopTopTopTopTopTopTopTopTopTopTopTopTopTopTop";
 51 
 52             Pagelet pagelet = new Pagelet()
 53             {
 54                 Css = "",
 55                 Html = Helper.RenderPartialViewToString(this, "TopPartial"),
 56                 //Js = "/Scripts/BigPipeT1.js",
 57                 Js = "",
 58                 Pid = "topId"
 59             };
 60             lock (_sysRoot)
 61             {
 62                 Response.Write("<script type='text/javascript'>PageLet.InitHtml(" + JsonConvert.SerializeObject(pagelet) + ");</script>");
 63                 Response.Flush();
 64                 Response.Clear();
 65             }
 66         }
 67 
 68         private void InitLeft()
 69         {
 70             ViewBag.Left = "bbbbbbbbbbbbbbbbbbbbbbb";
 71 
 72             Pagelet pagelet = new Pagelet()
 73             {
 74                 Css = "",
 75                 Html = Helper.RenderPartialViewToString(this, "LeftPartial"),
 76                 Js = "",
 77                 Pid = "leftId"
 78             };
 79             lock (_sysRoot)
 80             {
 81                 Response.Write("<script type='text/javascript'>PageLet.InitHtml(" + JsonConvert.SerializeObject(pagelet) + ");</script>");
 82                 Response.Flush();
 83                 Response.Clear();
 84             }
 85         }
 86 
 87         private void InitRight()
 88         {
 89            
 90             Pagelet pagelet = new Pagelet()
 91             {
 92                 Css = "",
 93                 Html = Helper.RenderPartialViewToString(this, "RightPartial"),
 94                 Js = "",
 95                 Pid = "rightId"
 96             };
 97             lock (_sysRoot)
 98             {
 99                 Response.Write("<script type='text/javascript'>PageLet.InitHtml(" + JsonConvert.SerializeObject(pagelet) + ");</script>");
100                 Response.Flush();
101                 Response.Clear();
102             }
103         }
104 
105         private void InitFoot()
106         {
107             lock (_sysRoot)
108             {
109                 Response.Write(
110                 new Pagelet()
111                 {
112                     Css = "",
113                     Html = Helper.RenderPartialViewToString(this, "FootPartial"),
114                     Js = "",
115                     Pid = "footId",
116                     PartialViewName = "FootPartial"
117 
118                 }.RenderHtml(this));
119                 Response.Flush();
120                 Response.Clear();
121             }
122         }
123 
124         /// <summary>
125         /// 初始化HTML网页框架
126         /// </summary>
127         private void InitHomeHtml()
128         {
129             var str = Helper.RenderPartialViewToString(this, "Index");
130             Response.Write(str);
131             Response.Flush();
132             Response.Clear();
133         }
134     }
135 }
View Code

     

三,总结

    BigPipe和Ajax二者区别:对于一个分成若干个块的页面而言,如果使用Ajax的话,每一块都需要单独发送一个HTTP请求,而如果使用BigPipe的话,不管有多少块,都仅有一个HTTP请

                                     求。所以Ajax对服务器造成的压力会是BigPipe的若干倍。

     BigPipe优点:速度快,将页面分割成多个pagelet,后台代码会为每个pagelet开启线程执行代码逻辑,执行完后立即输出到前端

     BigPipe缺点:不利于SEO, 对于这点可以写两份代码,一份使用bigpipe,一份不使用, 用User Agen判断访问者是用户还是搜索引擎,分别执行对应的那份代码。当然这样工作量增加了。

 

下载源码

 

你可能感兴趣的:(高性能)