用户
 找回密码
 入住 CI 中国社区
搜索
楼主: 方达
收起左侧

[Web] 关于CodeIgniter实现BigPipe的一些讨论

  [复制链接]
 楼主| 发表于 2012-7-3 23:35:08 | 显示全部楼层
太尉天上飞 发表于 2012-7-3 23:27
1、首先$this->load->view('skeleton'); 只是加载视图,结果被写入缓冲区而不直接输出。
2、即使想实现flus ...

谢谢回复!

对第一点,这个我认同的你的,而且我认为是在调用Output.php中的_dispaly()之后才输出的,不知道对我的理解你是不是认同呢?
对第二点的确没有试过将第三各参数设为TRUE之后再写flush相关代码的情况,我接着我自己尝试一下,谢谢给我这么重要的提示!
对第三点,我之前不用CI框架写过类似的实例,前面几个页面块在浏览器中先显示时,html结构在最后一个页面块未显示之前的确是不完整的(最后还是会补上),但并没有出现不能显示的问题。这主要是由于http1.1协议里支持chunk encoding的缘故,所以这种情况的出现是可以接受的。
 楼主| 发表于 2012-7-3 23:53:26 | 显示全部楼层
太尉天上飞 发表于 2012-7-3 23:27
1、首先$this->load->view('skeleton'); 只是加载视图,结果被写入缓冲区而不直接输出。
2、即使想实现flus ...

哎呦,对你第二点的提到的解决方案,我自己试了一下,虽然结果浏览器还是到全加载后才输出,而且从log文件看是skeleton先输出,2秒后content再输出。

但也不是没有收获:
从log里我发现这两个页面块最后输出前还是调用_dispaly()的。
也就是说
ob_start();
echo $this->load->view('skeleton', array(), TRUE);
ob_flush();
的写法,最后输出还是会通过调用Output.php中的_dispaly()输出。

其实自己之前不知所措的时候会在各种地方加,什么ob_start(),ob_flush(),ob_end_flush()什么的...最后都不太work,可伤心了...
 楼主| 发表于 2012-7-3 23:54:25 | 显示全部楼层
太尉天上飞 发表于 2012-7-3 23:27
1、首先$this->load->view('skeleton'); 只是加载视图,结果被写入缓冲区而不直接输出。
2、即使想实现flus ...

想追问一下你平时用的CI版本是多少呢?我现在是在2.1.1下写的,不知道是不是版本问题呢。
 楼主| 发表于 2012-7-4 00:01:15 | 显示全部楼层
太尉天上飞 发表于 2012-7-3 23:27
1、首先$this->load->view('skeleton'); 只是加载视图,结果被写入缓冲区而不直接输出。
2、即使想实现flus ...

对不住,我之前有个地方说的不对,你的第二点建议是不通过_dispaly()的,是直接flush的...哎呀,我今天被这个问题搞的自己连些概念都糊涂了..
发表于 2012-7-4 11:32:41 | 显示全部楼层
LS是正解  不过我的建议是按照区块 通过外部 如 AJAX调用的方式来解决广告的问题

评分

参与人数 1威望 +3 收起 理由
方达 + 3 的确是一种解决方案,虽然我不想这么做.

查看全部评分

 楼主| 发表于 2012-7-4 12:14:14 | 显示全部楼层
暗夜星辰 发表于 2012-7-4 11:32
LS是正解  不过我的建议是按照区块 通过外部 如 AJAX调用的方式来解决广告的问题 ...

的确呢,ajax是可以实现异步加载的,我明白的。


我想换种方式是因为,ajax会带来额外的浏览器向服务器的请求,
对一个访问量比较大的网站(比如facebook或者淘宝)
用ajax来做对服务器是一个考验,所以我想这么做的原因是想通过一次browser向server的请求,来达到分区块像流水线一样的加载。而不是ajax,通过多次browser向server的请求,来做到异步加载。

事实上,我想这么做是受到facebook做页面加载方式的启发的,他们把这种方式称为bigpipe。
在前年6月份facebook的一个工程师还专门写了一篇文章
http://www.facebook.com/note.php?note_id=389414033919
如果看facebook页面的源码,会发现一开始是一个skeleton,接下来是紧跟着许许多多的json对象的。
淘宝一个工程师在去年也有一篇文章来说这个问题的,而且也和ajax作了一些比较。
http://www.searchtb.com/2011/04/an-introduction-to-bigpipe.html

因为我的本意就是要尝试用bigpipe的方式,所以不想用ajax来做。
发表于 2012-7-4 13:19:06 | 显示全部楼层
看了taobao的文章,实现方式跟你的对比下,楼主应该很清楚。他们使用动态js组装dom的方式来实现的。首先flush整个html,然后再flush主体内容的一段js代码。简单例子:
1、
首先flush
<html>
<div id="body"></div>
</html>
浏览器先显示(此时http请求未关闭)
2、flush
<script type="text/javascript">document.getElementById('body').innerHTML = 'abc';</script>

结果……
 楼主| 发表于 2012-7-4 17:38:28 | 显示全部楼层
太尉天上飞 发表于 2012-7-4 13:19
看了taobao的文章,实现方式跟你的对比下,楼主应该很清楚。他们使用动态js组装dom的方式来实现的。首先flu ...

我问题解决了....
当知道真相,我眼泪都要留下来了...

说到底是我水平不太好...基础不扎实了...对http协议不了解了

最后的结果是因为我第一个加载的view模块缺少一个标签,即
<meta http-equiv="Content-Type" content="text/html"; charset=utf-8">

有这个标签就能实现分部flush,没这个标签无论如何都不能分部flush

我想请教一下,你认为为什么会这样呢?
我想听听你的看法呢,谢谢!我自己也会查资料的
 楼主| 发表于 2012-7-4 17:40:59 | 显示全部楼层
暗夜星辰 发表于 2012-7-4 11:32
LS是正解  不过我的建议是按照区块 通过外部 如 AJAX调用的方式来解决广告的问题 ...

我的问题解决了,最后其实是因为,
我加载的view中,html标签在头部缺少一个
<meta http-equiv="Content-Type" content="text/html"; charset=utf-8">

有它即能flush,没有它便不能....

和CI无关,和PHP无关....

CI是各好框架,是我水平不够好= = 对不住了...
 楼主| 发表于 2012-7-4 17:47:42 | 显示全部楼层
本帖最后由 方达 于 2012-7-4 23:20 编辑
cdm 发表于 2012-7-3 22:11
亲~~~   这个貌似不关框架的事,严格说起来也不太关php的事。

虽然没用过,但Bigpipe 原理大约是用js来加 ...

你的直觉是对的,我问题最后解决了,"不关框架的事,严格说起来也不太关php的事" :)

事实是在我加载的skeleton中,缺少一个
"<meta http-equiv="Content-Type" content="text/html"; charset=utf-8">"
的标签。有它即work,没有它即不work。

所以CI框架是可以用来实现前后端流水线般的工作的。是可以实现BIGPIPE思想的。

具体为:
1.第一个加载的view中,务必包含<meta...>标签
2.
PHP复制代码
 
ob_start();
echo $this->load->view('skeleton',array(),TRUE);
ob_flush();
flush();
echo $this->load->view('content',array(),TRUE);
ob_flush();
flush();
 
复制代码

所以我昨天这个问题本身考虑的角度就有问题了,对不住= =

另外你可以参考"太尉天上飞“的观点

评分

参与人数 1威望 +5 收起 理由
cdm + 5 感谢反馈问题所在

查看全部评分

本版积分规则