BigPipe是facebook发明的一种页面加载技术。其实也不是什么新技术了,也有很多文章进行说明。但是在网上,具体讲如何使用php实现bigpipe的文章很少,并且有些文章还不很准确。bigpipe的核心思想是并行。作为后端也要并行数据处理,这样才能使bigpipe发挥最大的威力。
在实现bigpipe时有几点注意:
1.如果使用nginx作为web服务器,那么nginx可能会缓冲php的输出。即便是调用了flush方法,相应内容也会被nginx缓冲,而不会输出到浏览器。
2.某些浏览器也会有缓冲,如在接收的数据小于一定值的时候,不会对代码进行渲染。

以下是一个demo示例代码:

<?php
header("Transfer-Encoding","chunked");
ini_set("output_buffering",0);
?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>php实现BigPipe</title>
<style type="text/css">
<!--
body {
font-size:12px;
text-align:left;
}
#head {
width:100%;
height:40px;
background:#8CAADE;
font-weight:bold;
color:#FFFFFF;
line-height:40px;
text-align:center;
font-size:16px;
}
#body {
margin:5px auto 5px auto;
width:800px;
border:solid 1px #8CAADE;
padding:10px;
line-height:30px;
}
#left {
float:left;
width:50%;
border:0px;
line-height:23px;
}
#right {
float:right;
width:50%;
border:0px;
line-height:23px;
}
#result {
width:800px;
height:30px;
text-align:center;
}
#bottom {
margin-top:5px;
width:800px;
height:30px;
text-align:center;
display:none;
}
#bottom a {
color:red;
text-decoration:none;
}
-->
</style>
<script>
function update(id, content) {
document.getElementById(id).innerHTML = content;
}
</script>
</head>
<?php
ob_flush();
flush();
?>
<body>
<div id="head">php实现BigPipe</div>
<div id="body">
<div>
本demo旨在演示php的并发处理在bigpipe中的应用。因此,在一些细节上实现的比较简单。但是,demo完全体现了bigpipe的并行数据处理和并行加载。<br/>
慢动作体现的是后端php串行处理时的效果。
</div>
<div id="cost_time"></div>
<?php
/*
* @purpose: 使用curl并行处理url
* @return: array 每个url获取的数据
* @param: $urls array url列表
* @param: $callback string 需要进行内容处理的回调函数。示例:func(array)
*/
function curl($urls = array(), $callback = '')
{
$response = array();
if (empty($urls)) {
return $response;
}
$chs = curl_multi_init();
$map = array();
foreach($urls as $url){
$cookie_file = "/temp/".md5($url).".txt";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_NOSIGNAL, true);
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);

curl_multi_add_handle($chs, $ch);
$map[strval($ch)] = $url;
}
do{
if (($status = curl_multi_exec($chs, $active)) != CURLM_CALL_MULTI_PERFORM) {
if ($status != CURLM_OK) { break; } //如果没有准备就绪,就再次调用curl_multi_exec
while ($done = curl_multi_info_read($chs)) {
$info = curl_getinfo($done["handle"]);
$error = curl_error($done["handle"]);
$result = curl_multi_getcontent($done["handle"]);
$url = $map[strval($done["handle"])];
$rtn = compact('info', 'error', 'result', 'url');
if (trim($callback)) {
$callback($rtn);
}
$response[$url] = $rtn;
curl_multi_remove_handle($chs, $done['handle']);
curl_close($done['handle']);
//如果仍然有未处理完毕的句柄,那么就select
if ($active > 0) {
curl_multi_select($chs, 0.5); //此处会导致阻塞大概0.5秒。
}
}
}
}
while($active); //还有句柄处理还在进行中
curl_multi_close($chs);
return $response;
}

//使用方法
function deal($data){
$url_info = parse_url($data["url"]);
$content_id = "content_".md5($data["url"]);
if ($data["error"] == "") {
$content = $url_info["host"]."&nbsp;&nbsp;能正常打开";
echo "<script>update('$content_id', '$content')</script>";
} else {
$content = $url_info["host"]."&nbsp;&nbsp;访问失败。具体错误原因:".$data["error"];
echo "<script>update('$content_id', '$content')</script>";
}
//因为浏览器有缓冲,即获取数据后,不会马上渲染。当获取数据大于一个值时开始渲染。
echo str_repeat(' ',1024);
ob_flush();
flush();
if (!empty($_GET["m"]) && $_GET["m"] == "slow") {
sleep(1);
}
}

$keyword = "一淘网";
$google_urls = array(
'http://www.google.com.br',//巴西
'http://www.google.ch',//瑞士
'http://www.google.nl',//荷兰
'http://www.google.com.au',//澳大利亚
'http://www.google.co.in',//印度
'http://www.google.ro',//罗马尼亚
'http://www.google.co.th',//泰国
'http://www.google.com.sa',//沙特阿拉伯
'http://www.google.co.jp',//日本
'http://www.google.com.my',//马来西亚
'http://www.google.ca',//加拿大
'http://www.google.com.tw',//中国台湾
);

$google_num = 10;//从google网址中取几个
$keys = array_rand($google_urls,$google_num);
$urls[] = "http://www.baidu.com/s?wd=".urlencode($keyword);
$urls[] = "http://www.etao.com";
for ( $i = 0; $i < $google_num; $i++) {
$urls[] = $google_urls[$keys[$i]]."/search?sclient=psy-ab&hl=en&site=&source=hp&q=".urlencode($keyword);
}
ob_start();
//生成占位div
foreach($urls as $url){
echo "<div class='item' id='content_".md5($url)."'>{$url}&nbsp;&nbsp;检测中</div>";
}
//除了浏览器web服务器可能也会缓冲,如nginx的fastcgi_buffers。
echo str_repeat(' ',1024);
ob_end_flush();
ob_flush();
flush();

//开始获取搜索数据
$start = microtime(true);
curl($urls, "deal");
$cost_time = microtime(true) - $start;
echo "<script>update('cost_time', '耗时{$cost_time}秒&nbsp;&nbsp;<a href=\'?m=slow\'>查看慢动作</a>')</script>";
?>
</div>
</body>
</html>

原创文章转载于: php实现bigpipe | 博学无忧

演示地址: http://demo.bo56.com/bigpipe/

本文固定链接: http://www.bo56.com/php%e5%ae%9e%e7%8e%b0bigpipe/ | 博学无忧

注意:使用BigPipe时,前端尽量不要使用nginx作为前端web服务器。因为他的fast-cgi的buffer无法关闭。也不要启用gzip等压缩。

php通过curl实现bigpipe的更多相关文章

  1. BigPipe学习研究

    BigPipe学习研究   from: http://www.searchtb.com/2011/04/an-introduction-to-bigpipe.html 1. 技术背景 FaceBook ...

  2. [转载]BigPipe技术

    1. 技术背景 FaceBook页面加载技术 试想这样一个场景,一个经常访问的网站,每次打开它的页面都要要花费6 秒:同时另外一个网站提供了相似的服务,但响应时间只需3 秒,那么你会如何选择呢?数据表 ...

  3. 用 NodeJS 实现 BigPipe

    BigPipe 是 Facebook 开发的优化网页加载速度的技术.网上几乎没有用 node.js 实现的文章,实际上,不止于 node.js,BigPipe 用其他语言的实现在网上都很少见.以至于这 ...

  4. 网站前端优化技术 BigPipe分块处理技术

    前端优化已经到极致了么?业务还在为看到不停的而揪心么?还在为2秒率不达标苦恼么? 好吧我知道答案,大家一如既往的烦恼中... 那么接下来我们看看,facebook,淘宝,人人网,一淘都是怎么做前端优化 ...

  5. BigPipe 大的页面分割成一个一个管道

    bigpipe创新驱动力  node实现 具体实现 过去十年,现代web站点变得更加动态和内容化,交互性也逐步增强, 传统的页面处理的方式却没有保持一样的速度发展,越来越不能满足用户对极致性能的追求. ...

  6. 在PowerShell中使用curl(Invoke-WebRequest)

    前言 习惯了windows的界面模式就很难转去命令行,甚至以命令行发家的git也涌现出各种界面tool.然而命令行真的会比界面快的多,如果你是一个码农. situation:接到需求分析bug,需要访 ...

  7. php中实现的一个curl批处理的实例

    curl是利用URL语法在命令行方式下工作的开源文件传输工具 本文在php中实现了的一个curl批处理的实例. 代码如下: header("Content-Type:text/html;ch ...

  8. PHP curl 函数

    转载http://sunking.sinaapp.com/archives/111 最近使用curl的时候,发现了一个比较好用的函数,当然是初级者适用的一个函数,就是curl_getinfo(), 在 ...

  9. curl -w,–write-out参数详解

    顾名思义,write-out的作用就是输出点什么.curl的-w参数用于在一次完整且成功的操作后输出指定格式的内容到标准输出. 输出格式由普通字符串和任意数量的变量组成,输出变量需要按照%{varia ...

随机推荐

  1. C语言判断系统数据大/小端存储方式

    小端存储:数据的低位部分,存储于存储器的低地址空间里. 大端存储:数据的低位部分,存储于存储器的高地址空间里. 首先,一般PC数据存储方式是小端存储. 基本实现思想是:将存储器中所存的数据按字节以地址 ...

  2. DateTime日期格式获取 分类: C# 2014-04-15 10:36 233人阅读 评论(0) 收藏

    c#.net 获取时间年月日时分秒格式 //获取日期+时间 DateTime.Now.ToString();            // 2008-9-4 20:02:10 DateTime.Now. ...

  3. JSP基本语法

    在tomcat环境搭建一文中为大家详细的介绍了第一个JSP的程序--Hello World,大家都应该顺利的完成了吧,以此为一个开端,希望大家在学习java EE的路上乘风破浪,不断进步.今天,为大家 ...

  4. evernote出现"Invalid username and/or password"的情况

    evernote出现"Invalid username and/or password"的情况 evernote挺好用的,可是这几年用下来也遇到过狗血情况,几乎每次都是更新后出状况 ...

  5. linux两台server远程copy文件

    1.将远程机器的文件copy到本地 scp -r  root@10.10.15.25:/bea   /gg   将远程的/bea copy到/gg以下 -r  Recursively copy ent ...

  6. 谈论C++当然结果

    C++编程课程的考试已经结束.这是第一次OJCBT.摸着石头过河,考试没有给学生理解的说法.现在尘埃落定.一些交代. 先说大的成就的治疗原则.事实上,有很多的纠结. 按理说,合格的太,无法挂.但实际情 ...

  7. JAVA中的继承和覆盖

    java里面的继承是子类继承父类的一些方法和属性(除private属性和方法之外):对于父类的私有属性和方法子类是没有继承的.可是要想子类也能訪问到父类的私有属性,必须给私有属性以外界訪问的方法接口. ...

  8. TCP/IP协议原理与应用笔记10:TCP/IP协议族

    1. 协议族视图如下:(这里我们列举重要的,并不是所有的) (1)网络接入层(数据链路层 和 物理层): 通过接入的物理网络的 功能 和 覆盖范围 进行分析划分为: •LANs :局域网(Local ...

  9. Android真正意义上的无限轮播Banner

    在android开发的时候,经常会使用到轮播图,对于这种效果,一般情况下,我们都会使用一种叫做ViewPager的来实现. 传统的实现逻辑是自定义一个View继承ViewPager,在适配器中 将co ...

  10. centos 安装nginx

    centos 安装nginx 安装依赖 更换源 yum install http://mirrors.163.com/centos/6.8/extras/x86_64/Packages/epel-re ...