Facebook BigPipe技术

 

关于web应用,从html的产生,到客户端浏览器的渲染,有3个重要的组成部分:

 

1.html在服务端生成

2.网络传输

3.浏览器渲染

Facebook BigPipe技术_第1张图片

 

在html生成的过程中,可能会用到cache,可能会链接数据库等等,对于负责的html页面,都要经过很多业务流程

 

facebook的做法是使html的生成变成多个步骤,每生成一小部分html(facebook给这种编程模型起了个名字叫做PageLet),就发送到网络上,浏览器就先展示最先发送的一部分,使整个页面传输的过程流水化,提高页面呈现速度。

 

经过流水化的页面生成后,整个过程变为:

 

Facebook BigPipe技术_第2张图片

 

可以很直观的看到,经过流水化处理后,整体速度快了1倍。

 

下边是一个java实现的简易BigPipeDemo

 

package com.opencfg.web;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Facebook BigPipe Demo
 * 
 * @author haitao.tu
 * @date  2010-01-03
 */
public class BigPipeServlet extends HttpServlet {

	private static final long serialVersionUID = 1344983665902790319L;

	@Override
	protected void service(HttpServletRequest req,
			final HttpServletResponse resp) throws ServletException,
			IOException {
		PrintWriter writer = resp.getWriter();
		
		String doctype = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">";
		String head = "<html>"
			        + "<head>"
		            + "<meta http-equiv='Content-type' content='text/html; charset=utf-8' />"
		            + "<meta http-equiv=\"Content-language\" content=\"zh\" />";
		writer.write(doctype);
		writer.write(head);
		writer.write(build_script_function());
		writer.write("</head><body><div>loading...");
		build_frame(writer, "id1", "id2", "id3", "id4", "id5", "id6");
		writer.write("</div>");
		pagelet(writer, "id1", "PageLet1");
		sleep(4000);
		pagelet(writer, "id2", "PageLet2");
		sleep(4000);
		pagelet(writer, "id3", "PageLet3");
		sleep(4000);
		pagelet(writer, "id4", "PageLet4");
		sleep(4000);
		pagelet(writer, "id5", "PageLet5");
		sleep(4000);
		pagelet(writer, "id6", "PageLet6");
		writer.write("</body></html>");
		writer.close();
	}

	/**
	 * 构造页面原型
	 */
	private void build_frame(PrintWriter writer, String... ids) {
		for (String id : ids) {
			writer.write("<div id='" + id + "'>-</div>");
		}
	}
	
	/**
	 * 构造javascript方法
	 */
	private String build_script_function() {
		return "<script type='text/javascript'>function show(id,text){document.getElementById(id).innerHTML = text;}</script>";
	}
	
	/**
	 * 构造javascript调用
	 */
	private String build_script_call(String id, String content) {
		return "<script>show('" + id+ "','" + content + "')</script>";
	}

	/**
	 * 发送facebook pagelet html包
	 */
	private void pagelet(PrintWriter writer, String id, String content) {
		if(writer.checkError())
			return;
		writer.write(build_script_call(id, content));
		writer.flush();
	}
	
	private void sleep(int times) {
		try {
			Thread.sleep(times);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

 

 

下边用wireshark抓包,看下是否产生想要的流水效果:

 

Facebook BigPipe技术_第3张图片

 

图中可以看出"TCP segment",至于收到一个报文后如何确定它是一个"TCP segment"?

 

如果有几个报文的ACK序号都一样,并且这些报文的Sequence Number都不一样,并且后一个Sequence Number为前一个Sequence Number加上前一个报文大小再加上1的话,肯定是TCP segment了。

 

在硬件上有很多网络设备可以在收到TCP大报文后切分成小报文发送出去,但是BigPipe的意义在于流水化,从而使用户尽可能快的得到页面响应。

 

以上是个人浅显的理解,希望以后能继续深入:)

 

 

你可能感兴趣的:(JavaScript,servlet,浏览器,网络应用,Facebook)