BearRui(AK-47)
花开有时,错过了一日便错过了一季,就象人生错过了相遇,就不再找寻到美丽的相聚
随笔- 39  文章- 2  评论- 1287 
博客园  首页  新随笔  联系  管理  订阅 订阅
高性能WEB开发(11) - flush让页面分块,逐步呈现

      在处理比较耗时的请求的时候,我们总希望先让用户先看到部分内容,让用户知道系统正在进行处理,而不是无响应。一般大家在处理这种情况,都使用ajax,先把html输出到客户端,然后再用ajax取加载比较耗时的资源。用ajax麻烦的地方是增加了请求数,而且需要写额外的js代码、和js调用的请求接口。

      正对这种情况,还有一种处理方法,就是让response分块编码进行传输。response分块编码,可以先传输一部分不需要处理的html代码到客户端,等其他耗时代码执行完毕后再传输另外的html代码。

 

分块编码(chunked encoding)

      chunked encoding 是http1.1 才支持编码格式(当然目前没有哪个浏览器不支持1.1了),chunked encoding 与一般的响应区别如下:

 

    正常的响应:

    HTTP/1.1 200 OK

    Cache-Control: private, max-age=60

    Content-Length: 75785

    Content-Type: text/html; charset=utf-8

    ..其他response headers

   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 

 

    chunked encoding 响应:

    HTTP/1.1 200 OK

    Cache-Control: private, max-age=60

    Content-Length: 75785

    Content-Type: text/html; charset=utf-8

    Transfer-Encoding: chunked

    ..其他response headers

    chunk #1(这里通常是16进制的数字,标志这个块的大小)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"....

  

    chunk #2

    <div .....

 

    chunk #3

    ....</body></html>

 

实例(JSP)

     一个简单的页面,分为头部(header)和内容(部分),假设内容部分需要读取数据库,花费3秒时间,然后显示csdn的logo。header部分显示cnblogs的logo。代码如下:

<body>
	<div id="head" style="border:1px solid #ccc;">
	   cnblogs logo <img src="http://images.cnblogs.com/logo_small.gif" />   
	</div>
	<br />
	<div id="content" style="border:1px solid blue;">
	<%
		// 睡眠3秒
		Thread.currentThread().sleep(3000);
	%>
		csdn logo<br />
		<img src="http://csdnimg.cn/www/images/csdnindex_piclogo.gif" />   
	</div>
</body>

  演示地址:http://213.186.44.204:8080/ChunkTest/nochunk.jsp (服务器比较差,请大家温柔点)

  打开这个演示地址发现很正常的页面,在3秒后才开始下载显示2个logo,资源加载瀑布图如下: 

  

 

 

  现在把代码改成如下,加上flush,让response把之前的html分块输出:

  <div id="head" style="border:1px solid #ccc;">

   cnblogs logo <img src="http://images.cnblogs.com/logo_small.gif" />   
</div>
<%
	out.flush(); // flush response,分块输出
%>
<br />
<div id="content" style="border:1px solid blue;">
	<%
		// 睡眠3秒
		Thread.currentThread().sleep(3000);
	%>
	csdn logo<br />
	<img src="http://csdnimg.cn/www/images/csdnindex_piclogo.gif" />   
</div>

   演示地址:http://213.186.44.204:8080/ChunkTest/chunk.jsp

   打开这个演示地址,是不是发现cnblogs logo先下载显示出来,3秒后csdn logo才显示,资源加载图如下:

  

   从这个图发现,cnblogs的logo在jsp页面还没执行完就开始下载了,这就是分块输出的效果。

 

监控工具:

      如何知道我们是否成功使用了chunk encoding了 ,只要用工具查看response header 中是否包含了Transfer-Encoding: chunked,如果包含了,则是分块了。但要想监控分块的详细信息,据我所知,目前只有httpwatch支持,可以查看我们到底分了多少块,但是数量好像都多显示了1个,如下图:

    

 

    有需要请查看:高性能WEB开发系列

[作者]:BearRui(AK-47)
[博客]: http://www.cnblogs.com/BearsTaR/
[声明]:本博所有文章版权归作者所有(除特殊说明以外),转载请注明出处.
绿色通道:好文要顶关注我收藏该文与我联系
posted on 2010-05-19 10:18 BearRui(AK-47) 阅读(10299) 评论(77) 编辑 收藏
发表评论
2198016
 回复 引用 查看   
#1楼 2010-05-19 10:29 | Snake@Net      
这个东东好!
 回复 引用   
#2楼 2010-05-19 10:42 | g.s[未注册用户]
这个只能说协议必须是http1.1
 回复 引用 查看   
#3楼 2010-05-19 10:47 | 舞千愁      
网站Div重叠了,能换个模板不?我是IE8
 回复 引用 查看   
#4楼[楼主] 2010-05-19 10:48 | BearRui(AK-47)      
引用g.s:这个只能说协议必须是http1.1

对,但是目前所有浏览器都是使用http1.1,就算使用1.0进行请求,也不会有影响,只是chunk会失效,又变成最原始的nochunk请求。

 回复 引用 查看   
#5楼[楼主] 2010-05-19 10:48 | BearRui(AK-47)      
引用Snake@Net:这个东东好!

谢谢

 回复 引用   
#6楼 2010-05-19 10:48 | g.s[未注册用户]
引用BearRui(AK-47):
引用g.s:这个只能说协议必须是http1.1

对,但是目前所有浏览器都是使用http1.1,就算使用1.0进行请求,也不会有影响,只是chunk会失效,又变成最原始的nochunk请求。


呵呵,浏览器还好,主要是CDN和proxy,毕竟中国的网络环境参差不齐

 回复 引用 查看   
#7楼[楼主] 2010-05-19 10:50 | BearRui(AK-47)      
引用舞千愁:网站Div重叠了,能换个模板不?我是IE8

你好,请问你是只这篇文章出现问题,还是我所有博客内容都出现问题,IE8是否能开启兼容模式看下有没有问题,如果还有问题,我就换个模板,觉的这个模板挺鲜艳,呵呵。

 回复 引用 查看   
#8楼[楼主] 2010-05-19 10:51 | BearRui(AK-47)      
引用g.s:
呵呵,浏览器还好,主要是CDN和proxy,毕竟中国的网络环境参差不齐


对CDN和proxy 不是特别了解,HTTP1.1 出现那么久了,还不支持啊。

 回复 引用 查看   
#9楼 2010-05-19 11:24 | 黑色      
收藏下
 回复 引用 查看   
#10楼 2010-05-19 12:57 | Fisher WEI      
JSP...
 回复 引用 查看   
#11楼[楼主] 2010-05-19 13:10 | BearRui(AK-47)      
引用Fisher WEI:JSP...

实例是JSP写的,ASP.NET原理是一样的

 回复 引用 查看   
#12楼 2010-05-19 14:17 | sohighthesky      
@BearRui(AK-47)
.net中添加
protected override void OnInit(EventArgs e)
        {
            Response.AddHeader("Transfer-Encoding","chunked");
            base.OnInit(e);
        }

添加之后页面打不开了,
去掉这句之后 ,同样有你那个效果

 回复 引用 查看   
#13楼[楼主] 2010-05-19 14:43 | BearRui(AK-47)      
引用sohighthesky:
@BearRui(AK-47)
.net中添加
protected override void OnInit(EventArgs e)
        {
            Response.AddHeader("Transfer-Encoding","chunked");
            base.OnInit(e);
        }

添加之后页面打不开了,
去掉这句之后 ,同样有你那个效果


不是直接添加header就可以的,需要使用flush,使用flush后,会自动添加header,不要再.cs文件中测试,因为.cs文件中会先执行OnInit的所有代码后才会输出aspx中的代码。你怎么测试会有这个效果。

 回复 引用 查看   
#14楼 2010-05-19 14:53 | sohighthesky      
使用flush后没看到http头里有那个Transfer-Encoding
 回复 引用 查看   
#15楼[楼主] 2010-05-19 14:57 | BearRui(AK-47)      
引用sohighthesky:使用flush后没看到http头里有那个Transfer-Encoding

我不知道net应该使用哪个flush,java中不能直接使用response.的flush方法,要使用response.getWriter().flush(),我的代码中使用的是out.flush(),而不是response.flush(),你看看asp.net中使用哪个对象来输出HTML,就用哪个对象flush

 回复 引用 查看   
#16楼 2010-05-19 19:00 | ITniao      
Response.BufferOutput 用这个?
 回复 引用 查看   
#17楼[楼主] 2010-05-19 22:30 | BearRui(AK-47)      
@ITniao
一个是吧,要试试才知道。

 回复 引用 查看   
#18楼 2010-05-25 13:30 | goguoguo土豆      
网站性能优化,这里有一些总结的比较好的。个人觉得不错,推荐一下:
http://www.tu321.com/index.php/tag/%E7%BD%91%E7%AB%99%E4%BC%98%E5%8C%96/

 回复 引用 查看   
#19楼 2010-06-18 09:09 | 阿三      
好文章,顶一下!
 回复 引用   
#20楼 2010-06-18 09:16 | wefwef[未注册用户]
在html页面输入Response.Flush()就行
 回复 引用 查看   
#21楼[楼主] 2010-06-18 09:19 | BearRui(AK-47)      
@wefwef
html页面中怎么使用response对象?

 回复 引用 查看   
#22楼 2010-06-18 09:33 | Chao yang      
好文章,顶一下!
 回复 引用 查看   
#23楼 2010-06-18 09:43 | argu      
好文章,顶一下!
 回复 引用 查看   
#24楼 2010-06-18 09:44 | 飞奔的蜗牛      
好文章,顶一下!
 回复 引用 查看   
#25楼[楼主] 2010-06-18 09:50 | BearRui(AK-47)      
谢谢楼上几位的支持,:D
 回复 引用 查看   
#26楼 2010-06-18 10:13 | 希望的田野      
这个系列很棒
学了不少东西!

 回复 引用 查看   
#27楼 2010-06-18 10:13 | 再快一点      
楼主您好,我在Asp.net中使用如下代码<%Response.BufferOutput = false; Response.Flush(); %>,结果在火狐中能实现页面分块逐步呈现,IE却不行,这是为什么呢?
 回复 引用 查看   
#28楼 2010-06-18 10:29 | Fs.song      
好文章,顶一下!
 回复 引用 查看   
#29楼[楼主] 2010-06-18 10:31 | BearRui(AK-47)      
@再快一点

看下你的IE发送到请求是不是http 1.1的,最好请使用httpwatch对请求进行监控,就知道你使用是否正确。

 回复 引用 查看   
#30楼[楼主] 2010-06-18 10:32 | BearRui(AK-47)      
引用希望的田野:
这个系列很棒
学了不少东西!


谢谢,^_^

 回复 引用 查看   
#31楼 2010-06-18 10:37 | 再快一点      
呵呵,问题解决了,原来是我开了Fiddler,而Fiddler的原理是给IE使用代理服务器。
 回复 引用 查看   
#32楼[楼主] 2010-06-18 10:42 | BearRui(AK-47)      
解决了就好。
 回复 引用 查看   
#33楼 2010-06-18 11:53 | ygcao      
文章很精彩,推荐一下!
 回复 引用 查看   
#34楼 2010-06-18 13:24 | xsylk_cn      
文章写的一般般,:)
 回复 引用 查看   
#35楼 2010-06-18 13:42 | 西就东城      
文章写的一般般,:)
 回复 引用 查看   
#36楼 2010-06-18 13:46 | Laurence liu      
好文章,顶一下!
 回复 引用 查看   
#37楼 2010-06-18 13:50 | Michael_Xu      
好文章,顶一下!
 回复 引用 查看   
#38楼 2010-06-18 13:50 | Michael_Xu      
文章很精彩,推荐一下!
 回复 引用 查看   
#39楼 2010-06-18 14:09 | 良村      
文章很精彩,推荐一下!
 回复 引用 查看   
#40楼 2010-06-18 14:09 | 地磁人      
好文章,顶一下!
 回复 引用 查看   
#41楼 2010-06-18 15:53 | szyicol      
如果多个js之间有引用,分块如果没有注意,会不会造成页面报错?
 回复 引用 查看   
#42楼[楼主] 2010-06-18 15:57 | BearRui(AK-47)      
引用szyicol:如果多个js之间有引用,分块如果没有注意,会不会造成页面报错?


二当家啊,多个JS之间有引用的话,一般都需要按照顺序加载,除非你能保证你引用的js代码在全部JS下载完前不会被执行。

 回复 引用 查看   
#43楼 2010-06-18 16:19 | Paddle Zhou      
好文章,顶一下!
 回复 引用 查看   
#44楼 2010-06-18 16:47 | szyicol      
引用BearRui(AK-47):
引用szyicol:如果多个js之间有引用,分块如果没有注意,会不会造成页面报错?


二当家啊,多个JS之间有引用的话,一般都需要按照顺序加载,除非你能保证你引用的js代码在全部JS下载完前不会被执行。




嗯,偶写的管理系统,可能比较难搞。


out.flush(); // flush response,分块输出

这句代码是前台的js代码还是后台的代码,如果是后台,.net中是否有对应的代码?


 回复 引用 查看   
#45楼[楼主] 2010-06-18 16:54 | BearRui(AK-47)      
@szyicol
flush是后台代码,上面有网友说NET中使用<%Response.BufferOutput = false; Response.Flush(); %>

具体我也没试过,现在没有NET环境。

 回复 引用 查看   
#46楼 2010-06-18 17:57 | duncannjm      
好文章,顶一下!
 回复 引用 查看   
#47楼 2010-06-18 21:12 | 明天.Net      
好文章,顶一下!
 回复 引用 查看   
#48楼 2010-06-18 21:12 | 明天.Net      
文章写的一般般,:)
 回复 引用   
#49楼 2010-06-19 08:57 | oldmoon[未注册用户]
关注细节,不错
 回复 引用 查看   
#50楼[楼主] 2010-06-19 13:02 | BearRui(AK-47)      
@oldmoon
谢谢夸奖

 回复 引用 查看   
#51楼 2010-06-21 17:01 | BirchLee      
好文章,顶一下!
 回复 引用 查看   
#52楼 2010-06-21 17:01 | BirchLee      
文章很精彩,推荐一下!
 回复 引用 查看   
#53楼 2010-06-21 17:01 | BirchLee      
文章写的一般般,:)
 回复 引用 查看   
#54楼 2010-06-21 17:01 | BirchLee      
看不懂哦,~_~
 回复 引用 查看   
#55楼 2010-06-21 17:01 | BirchLee      
博主还需努力啊!
 回复 引用 查看   
#56楼 2010-06-22 15:09 | 阿武啦      
为什么80端口的就不行实现这个功能啦
 回复 引用 查看   
#57楼[楼主] 2010-06-22 15:12 | BearRui(AK-47)      
引用阿武啦:为什么80端口的就不行实现这个功能啦


不可能啊,这个跟端口肯定没关系,你用类似httpwatch的工具监控下你的请求看看。

 回复 引用 查看   
#58楼 2010-06-22 18:49 | 阿武啦      
@BearRui(AK-47)
引用BearRui(AK-47):
引用阿武啦:为什么80端口的就不行实现这个功能啦


不可能啊,这个跟端口肯定没关系,你用类似httpwatch的工具监控下你的请求看看。


http://213.186.44.204/ChunkTest/chunk.jsp(这个页面是同时显示的)
http://213.186.44.204:8080/ChunkTest/chunk.jsp(这个页面有分块显示)

我也在自己的网站上试过,也是这样

 回复 引用 查看   
#59楼[楼主] 2010-06-22 23:21 | BearRui(AK-47)      
不是,
引用阿武啦:
@BearRui(AK-47)
引用BearRui(AK-47):
引用阿武啦:为什么80端口的就不行实现这个功能啦


不可能啊,这个跟端口肯定没关系,你用类似httpwatch的工具监控下你的请求看看。


http://213.186.44.204/ChunkTest/chunk.jsp(这个页面是同时显示的)
http://213.186.44.204:8080/ChunkTest/chunk.jsp(这个页面有分块显示)

我也在自己的网站上试过,也是这样


我的80端口不行是正常的,因为我80端口用的是反向代理,8080端口才是直接访问的tomcat服务器。

 回复 引用   
#60楼 2010-06-24 17:30 | 关注Java[未注册用户]
牛B哥
 回复 引用 查看   
#61楼 2010-06-25 21:32 | DecleorMX      
如果一个网站使用了chunk技术,还能不能用httpRequest请求到完整的HTML页面?
 回复 引用 查看   
#62楼[楼主] 2010-06-25 22:52 | BearRui(AK-47)      
引用DecleorMX:如果一个网站使用了chunk技术,还能不能用httpRequest请求到完整的HTML页面?


可以请求到,因为chunk全部发送完毕后,httpRequest的readyState才会==4。

可以看我这篇随笔,就是使用ajax请求chunk页面的:
http://www.cnblogs.com/BearsTaR/archive/2010/06/02/ajax_better_Experience.html

 回复 引用 查看   
#63楼 2010-07-04 20:48 | 心不蒙尘      
Marked~~~~

好文章~~~~

 回复 引用 查看   
#64楼[楼主] 2010-07-05 09:15 | BearRui(AK-47)      
谢谢支持。
 回复 引用 查看   
#65楼 2010-07-08 09:57 | 不能飚车      
一直关注高性能web开发,这个系列写得不错~
 回复 引用 查看   
#66楼[楼主] 2010-07-08 10:35 | BearRui(AK-47)      
@不能飚车
谢谢支持,希望以后多点交流,^_^

 回复 引用 查看   
#67楼 2010-07-08 11:18 | 卡索      
呵呵 !好文章,读了几次,然后也做了个测试,你文中说的chunk数量的问题,本文你的测试是3,这个应该是没多的,你页面中使用一个flush后,页面最后需要使用一个0来结束。这是由于
Chunked编码使用若干个Chunk串连而成,由一个标明长度为0的chunk标示结束...

所以会比我们想得多一个chunk

 回复 引用 查看   
#68楼[楼主] 2010-07-08 13:22 | BearRui(AK-47)      
@卡索
对于chunk数量,不知道是不是如你所说的,最近比较忙,一直都没时间。等有时间再深入研究下,谢谢提醒,^_^

 回复 引用 查看   
#69楼 2010-08-04 15:05 | MicroCoder      
如果启动了gzip动态压缩的话 flush会失效或者不稳定!
 回复 引用 查看   
#70楼[楼主] 2010-08-04 15:11 | BearRui(AK-47)      
@MicroCoder
不会啊,网上用flush的网站几乎都启用了gzip

 回复 引用 查看   
#71楼 2010-08-05 10:45 | MicroCoder      
@BearRui(AK-47)
我以前遇见过 禁用gzip之后就好了,也没有深究

http://stackoverflow.com/questions/344430/response-flush-not-working-asp-net/2677321#2677321

 回复 引用 查看   
#72楼 2010-10-26 10:45 | 代码匠      
楼主用的监测工具是?
 回复 引用 查看   
#73楼[楼主] 2010-10-26 10:47 | BearRui(AK-47)      
@代码匠
HTTP WATCH,工具介绍可参考下面文章:
http://www.blogjava.net/BearRui/archive/2010/04/28/web_performance_tools.html

 回复 引用 查看   
#74楼 2010-10-26 14:51 | 代码匠      
3q,楼主
 回复 引用 查看   
#75楼[楼主] 2010-10-27 19:29 | BearRui(AK-47)      
不客气,^_^
 回复 引用 查看   
#76楼 2011-04-02 13:56 | 残荷      
不是多显示了一个,是由于chunk协议中通过长度为0的chunk段表示结束,所以就会默认加一个
 回复 引用 查看   
#77楼 2011-09-13 12:54 | sofakeer      
学习了!
刷新评论列表  刷新页面  返回页首
发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

验证码: 验证码 看不清,换一个

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1738872 K6KdrAsSI+A=
首页博问闪存新闻园子招聘知识库
最新IT新闻:
· 苹果员工称下一代iPad显示效果“令人惊叹”
· 海盗湾:2012是风暴之年
· 苹果市值超微软Google之和 超瑞典GDP
· LinkedIn四季度净利690万美元 同比增长30%
· 微软高管详解ARM版Win 8:提供Office 15
» 更多新闻...
最新知识库文章:
· 如何学习一门新的编程语言?
· 学习不同编程语言的重要性
· 为什么我喜欢富于表达性的编程语言
· 计算机专业的女生为什么要学编程
· 前端必读:浏览器内部工作原理
» 更多知识库文章...

China-pub 2011秋季教材巡展
China-Pub 计算机绝版图书按需印刷服务

抓虾
google reader
鲜果
哪吒
QQ邮箱
http://wap.feedsky.com/BearRui
昵称:BearRui(AK-47)
园龄:5年10个月
荣誉:推荐博客
粉丝:124
关注:3

搜索

 

最新随笔

  • 1. 产生唯一随机码的方法分析。
  • 2. URL中允许携带sessionid带来的安全隐患。
  • 3. JS 实现完美include
  • 4. 基于模板的excel导出
  • 5. 实现if elseif else的jsp标签。
  • 6. 记一复杂页面的前端优化(2) - 其他优化
  • 7. 记一复杂页面的前端优化(1) - 不一样的延迟加载
  • 8. 名站技术分析 — tudou网首页下列菜单的弹出效果
  • 9. LESS 让css也支持变量,运算符,include,嵌套规则等等
  • 10. CSS技巧 — 不使用图片实现圆角、阴影、渐变等功能

随笔分类(38)

  • .NET(11)
  • CSS(3)
  • JAVA(2)
  • javascript(4)
  • Life(5)
  • WEB(4)
  • 高性能WEB开发(5)
  • 浏览器(1)
  • 名站技术分析(3)

随笔档案(39)

  • 2010年10月 (1)
  • 2010年8月 (3)
  • 2010年7月 (5)
  • 2010年6月 (4)
  • 2010年5月 (6)
  • 2006年6月 (4)
  • 2006年5月 (7)
  • 2006年4月 (9)

积分与排名

  • 积分 - 178236
  • 排名 - 485

最新评论

阅读排行榜

评论排行榜

推荐排行榜

Copyright ©2012 BearRui(AK-47)