1
包头header中的,Transfer-Encoding: chunked 表示输出的内容长度不能确定,普通的静态页面、图片之类的基本上都用不到这个。
但动态页面就有可能会用到,但我也注意到大部分asp,php,http://asp.net**动态页面输出的时候大部分还是使用Content-Length,没有使用Transfer-Encoding: chunked。
不过如果结合:Content-Encoding: gzip 使用的时候,Transfer-Encoding: chunked还是比较有用的。
2
著名的 Yahoo Web 开发 14 条军规的第一条就是“减少你的 Http 请求”。当然这只是一个笼统的说法,或者是给我们指明一条优化的总则。毕竟我们要在“页面信息规模”和“Http 请求数”上做到一个取舍。不能因为“要减少 Http 请求数”而牺牲了用户体验。终归我们是要将信息通过 HTML 页面传达给用户的。 简单的说,如果我们只想简单的达到把信息传递给用户的目的。那我们可以将信息直接输出到浏览器上,可能一个 Http 请求就解决了问题。但这样的信息即便到达了用户的浏览器,用户也很难接受。白底黑子,乱呼呼的一堆,你想谁会喜欢看?所以我们在为用户传达信息的同时,我们需要加载 CSS、图片、js脚本等,通过各种复杂而生动的效果,让我们想要传达的信息更容易的为用户所接受。而我们要为此付出的代价就是“增加我们的 Http 请求数”。 我们需要更好的用户体验,让用户看到他们更容易接受的页面,这使得我们不断的增加了我们的 Http 请求数,这与我们的“军规”背道而驰,难道就没有一个“两全其美”的办法吗?当然是有的。 首先,我们可以充分利用浏览器缓存。把 CSS、js脚本和图片等静态文件缓存起来。当浏览器再次加载这些资源的时候,我们可以方便的从浏览器缓存中取得这些内容。从而大大减少我们发起的 Http 请求。这是一个普遍为大家所熟知而又简单有效的办法。但是请注意,浏览器缓存只是在我们再次请求同样的资源时才生效。我们暂且称之为“第二次请求优化”,而这无法解决“首次加载”时的问题。因为我们第一次去请求这些原本浏览器没有缓存的资源时,我们还是要老老实实的发送“Http 请求”的。 针对我们要研究的“首次加载优化”问题。我们在这里先做一个假设。假设我们要提供一篇文章给用户。这篇文章分为题目、文章简介、章节索引、章节内容四部分。当然我们为了文章的美观少不了要写 CSS 样式、准备一些插图和通过一些 JS 脚本控制我们的文章结构。那么当用户发起请求,向我们“索要”这篇文章时,我们如何做到快速响应,以避免用户等得不耐烦呢? 我们要展现给用户的文章是固定的。有题目、文章简介、章节索引、章节内容四部分。从用户发起请求想要阅读这篇文章,到我们提供文章给用户,为了更为直观的理解这个过程,我们将他们以慢动作的形式来展现。假设用户发起的想要阅读这篇文章的请求经过 1 秒钟到达我们的服务器。我们的服务器接收到这个请求,从数据库或是其他存储器中取得这篇文章,并按照题目、文章简介、章节索引、章节内容的结构组装好,这个过程花费了 4 秒钟,然后我们将这篇文章发送给用户用了 2 秒钟。用户从想要看这篇文章到看到了这篇文章,一共花费了 7 秒钟(当然没那么夸张,因为我们的服务器响应和网络传输基本都在毫秒级,我们只是将这个过程以“慢镜头”的形式在播放)。 这 7 秒钟意味着什么?意味着用户在点击鼠标表达想要阅读这篇文章到用户读到这篇文章前,他要呆呆的面对一张白花花的屏幕 7 秒钟。会有一部分用户因为不耐烦而关闭页面,因为没有几个人喜欢对着白屏发呆。 而如何在不牺牲用户体验(该加载的 CSS 样式、文章插图和 JS 脚本文件一个都不能少)的前提下减少用户的等待时间,就是我们需要解决的问题关键。解决这个问题比较通用的做法就是“分部加载”。就是在用户发出阅读请求的时候,并不等文章整体加载完成后再呈现给用户,而是将他们“打碎”。比如我们可以现将文章的题目呈现给用户,接着是文章简介,然后是章节索引,最后呈现章节内容。通过这样“打碎”文章结构,将文章一部分一部分的呈现给用户,我们也就“打碎”了用户的等待时间(用户不再等待 7 秒钟去看整篇文章,而是等上 1 秒钟就会看到文章题目,再等上 1 秒钟看到文章简介......通过“打碎”等待时间让用户有一种“很快响应”的错觉)。 写到这,熟悉 web 开发的读者可能会想到“用 Ajax 不就可以了吗!”。没错,Ajax 技术完全可以实现这种“分部加载”以提升用户体验,“减少”(并不是真正意义上的减少)响应延迟时间。我们可以在用户请求阅读这篇文章的时候,快速的加载一个体积较小的页面,页面中含有一些 JavaScript 语句,通过这些语句分别发送一些 Ajax 请求,这些请求有的去取文章题目,有的去取文章简介......并将取到的内容呈现在页面上,以减少用户一次性等待响应的时间。Ajax 是个不错的办法,但是想想我们的“军规”,我们要“减少 Http 请求数”!,而 Ajax 在提升用户体验,减少用户等待的同时最大的弊病就是增加了大量的“Http 请求次数”。 除了 Ajax 技术,还有别的办法吗?答案是肯定的。接下来就该是我们的 “Chunk 技术” 出场的时间了。Chunk 并不是什么新技术,而是 Http 协议的一个编码方式。简单的解释就是“服务器生成HTTP回应是无法确定消息大小的,这时用Content-Length就无法事先写入长度,而需要实时生成消息长度,这时服务器一般采用Chunked编码。 在进行Chunked编码传输时,在回复消息的头部有transfer-coding并定为Chunked,表示将用Chunked编码传输内容。”我们可以通过 FireBug 等调试工具查看服务器的 Http 响应头,看到有 transfer-coding 并且值为 Chunked 的,就表明采用了 Chunk 编码。 那么 Chunk 和我们所讨论的“分部加载”有什么关系呢?细心的读者可能已经看出来了,Http 的 Chunk 编码实际上就是一种将 Http 响应分部传送的方法。一个Http响应可以有若干个Chunk组成,由一个标明长度为0的chunk结束,每个Chunk有两部分组成,第一部分是该Chunk的长度和长度单位(一般不 写),第二部分就是指定长度的内容。而当浏览器接收到服务器的响应并判定响应是 Chunk 编码的,则浏览器可以在每接收一个 Chunk 段完毕时先行渲染这个 Chunk 段所携带的内容。这样就实现了“分部加载”的目的。 如何应用 Chunk 技术来进行“分部加载”呢?我们以一段 PHP 代码为例。 <?php $content = array("我是文章题目", "我是文章简介", "我是章节索引", "我是章节内容",); foreach ($content as $c) { echo "<p>$c</p>"; sleep(1); //我们这里故意放慢节奏,等待一秒 } ?> 假设我们想服务器请求一篇文章的时候由上述 PHP 脚本来响应这次请求。你会发现,你大概需要等待 4 秒钟后才会看到文章的全部内容(文章题目、文章简介、章节索引和章节内容)。我们再来看下面的这种通过 Chunk 来“分部加载”的代码实现: <?php $content = array("我是文章题目", "我是文章简介", "我是章节索引", "我是章节内容",); $buffer_size = 4096; foreach ($content as $c) { echo str_pad( "<p>$c</p>", $buffer_size); ob_flush(); flush(); sleep(1); //我们这里故意放慢节奏,等待一秒 } ?> 这次我们再来试试这段 PHP 代码作为响应文章请求时的效果。你会发现,你先看到了文章题目,1 秒钟后浏览器为你呈现了文章简介,又 1 秒钟后是章节索引,再 1 秒钟后章节内容也出来了。“分部加载”的效果出来了,你再也不同等待 4 秒钟了! 简单的解释一些上面的代码。PHP 本身是支持这种通过 Http Chunk 编码来响应请求的。我们每 echo 一段要输出的内容后,调用 ob_flush 和 flush 两个方法来清空缓存,这样 echo 的内容会直接发送给浏览器,达到“分部”完成响应的目的。 最后在说明一下“分部加载”时的 echo 为什么使用了 str_pad 方法。由于 PHP 本身缓存大小(php.ini 中的 ob_buffering),不同 web 服务器(Nginx、Apache)和浏览器不同的关系,当我们 echo 的内容过小时,即使调用了 ob_flush 和 flush 方法清空输出缓存,echo 的内容也未必会即时发送,这是我们就需要调用 str_pad 方法来让我们 echo 的内容“增肥”以达到占满缓存的目的。 对于实现“分部加载”,Ajax 和 Chunk 都可以达到同样的效果。但是由于 Chunk 不会产生额外的 Http 请求,所以更为轻盈(毕竟发起 Http 请求也是时分昂贵的!)。 Facebook 为我们大家所熟知(虽然我们无法使用),其用户个人主页信息量之大,结构之复杂也可见一斑。Facebook为了减少页面的响应时间,发明了一种他们称之为“BigPipe”的技术,这个技术的核心原理就是 Http 的 Chunk 编码。据Facebook的测试表明“BigPipe”技术使其页面响应时间减少了约 50% (FireFox3.6除外,用 FireFox3.6的响应时间减少约22%),可见很好的利用 Http Chunk 技术,可以大大提高我们 Http 的响应速度.
放上 Chunk 技术和 BigPipe 技术的相关文章,剩下的google
Chunk 技术:《flush让页面分块,逐步呈现》**
Facebook BigPipe 技术 : 《名站技术分析 — facebook奇特的页面加载技术》**《Facebook创新之BigPipe:优化页面加载时间》**《BigPipe: Pipelining web pages for high performance》**