假设你正在写一个基于多台服务器的php应用,假设你正在写一个基于多台服务器的php应用
分类:威尼斯手机平台

近日钻探php三十七线程的标题,开采中文财富少的特别,仅局地几篇文章被转了又转,但文中内容价值有限。寻觅进程中发掘海外众多网址引述的一篇小说写的不易,所以翻译过来。

问题:
有未有法子在php中贯彻多线程呢?
威尼斯手机平台,倘让你正在写一个基于多台服务器的php应用,理想的情状时同期向多台服务器发送乞求,并不是一台接一台。
能够完毕吗?
回答:
当有人想要完结并发功用时,他们经常会想到用fork或许spawn threads,可是当他俩发觉php不扶植多线程的时候,大约会转移思路去用一些非常不够好的语言,举个例子perl。
实际上的是好多场合下,你未有供给使用fork可能线程,况且你会收获比用fork或thread越来越好的性质。
只要你要白手成家一个劳务来检查正在周转的n台服务器,以明确他们还在健康运营。你也许会写上面那样的代码:
复制代码 代码如下:

版权评释:能够随意转发,转发时请必须以超链接格局注脚随笔原本出处和作者新闻及本表明难点:要是你正在写三个依据多台服务器的php应用,理想的场所时还要向多台服务器发送乞求,并非一台接一台。能够兑现呢?回答:

$hosts = array("host1.sample.com", "host2.sample.com", "host3.sample.com");
$timeout = 15; $status = array();
foreach ($hosts as $host) {
$errno = 0;
$errstr = "";
$s = fsockopen($host, 80, $errno, $errstr, $timeout);
if ($s) {
$status[$host] = "Connectedn";
fwrite($s, "HEAD / HTTP/1.0rnHost: $hostrnrn");
do {
$data = fread($s, 8192);
if (strlen($data) == 0) { break; }
$status[$host] .= $data;
} while (true); fclose($s);
} else {
$status[$host] = "Connection failed: $errno $errstrn";
}
}
print_r($status);
?>

当有人想要达成并发作用时,他们平日会想到用fork大概spawn threads,可是当他们开掘php不补助二十四线程的时候,大致会退换思路去用一些非常不够好的言语,举个例子perl。

它运维的很好,可是在fsockopen(State of Qatar解析完hostname况且创制四个中标的总是(可能延时$timeout秒)早先,扩大这段代码来管理多量服务器将消耗相当长日子。
由此我们必须要遗弃这段代码;我们得以成创新步连接-无需翘首以待fsockopen重返连接情形。PHP仍旧须求剖析hostname(所以直接行使ip更加明智),然则将要展开叁个接二连三之后立即回去,进而大家就可以连接下一台服务器。
有二种办法能够兑现;PHP5中可以动用激增的stream_socket_client(卡塔尔国函数直接交流掉fsocketopen(卡塔尔国。PHP5早先的 版本,你须要本人出手,用sockets扩大搞定难题。
上边是PHP5中的搞定措施:
复制代码 代码如下:

实际的是大多地方下,你没有需要使用fork大概线程,况兼你会获取比用fork或thread越来越好的个性。

$hosts = array("host1.sample.com", "host2.sample.com", "host3.sample.com");
$timeout = 15;
$status = array();
$sockets = array();
foreach ($hosts as $id => $host) {
$s = stream_socket_client("$host:80", $errno, $errstr, $timeout,STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT);
if ($s) {
$sockets[$id] = $s;
$status[$id] = "in progress";
} else {
$status[$id] = "failed, $errno $errstr";
}
}
while (count($sockets)) {
$read = $write = $sockets;
$n = stream_select($read, $write, $e = null, $timeout);
if ($n > 0) {
foreach ($read as $r) {
$id = array_search($r, $sockets);
$data = fread($r, 8192);
if (strlen($data) == 0) {
if ($status[$id] == "in progress") {
$status[$id] = "failed to connect";
}
fclose($r);
unset($sockets[$id]);
} else {
$status[$id] .= $data;
}
}
foreach ($write as $w) {
$id = array_search($w, $sockets);
fwrite($w, "HEAD / HTTP/1.0rnHost: " . $hosts[$id] . "rnrn");
$status[$id] = "waiting for response";
}
} else {
foreach ($sockets as $id => $s) {
$status[$id] = "timed out " . $status[$id];
}
break;
}
}
foreach ($hosts as $id => $host) {
echo "Host: $hostn"; echo "Status: " . $status[$id] . "nn";
}
?>

假让你要成立三个劳务来检查正在周转的n台服务器,以明确他们还在常规运转。你恐怕会写下边那样的代码:

我们用stream_select(卡塔尔(قطر‎等待sockets张开的三番若干遍事件。stream_select(卡塔尔调用系统的select(2卡塔尔国函数来工作:后面两个参数是你要采纳的streams的数组;你能够对其读取,写入和收获卓殊(分别针对多少个参数)。stream_select(State of Qatar能够通过设 置$timeout(秒)参数来等待事件产生-事件发生时,相应的sockets数据将写入你传入的参数。
下边是PHP4.1.0后头版本的实现,若是你曾在编写翻译PHP时包蕴了sockets(ext/sockets卡塔尔(قطر‎援救,你能够动用根上面相像的代 码,只是要求将上边的streams/filesystem函数的效劳用ext/sockets函数达成。首要的两样在于我们用下边包车型地铁函数替代stream_socket_client(卡塔尔(قطر‎来树立连接:
复制代码 代码如下:

?php$hosts = array(host1.sample.com, host2.sample.com, host3.sample.com);$timeout = 15;$status = array();foreach ($hosts as $host) { $errno = 0; $errstr = ; $s = fsockopen($host, 80, $errno, $errstr, $timeout); if ($s) { $status[$host] = Connectedn; fwrite($s, HEAD / HTTP/1.0rnHost: $hostrnrn); do { $data = fread($s, 8192); if (strlen($data) == 0) { break; } $status[$host] .= $data; } while (true); fclose($s); } else { $status[$host] = Connection failed: $errno $errstrn; }}print_r($status);?

// This value is correct for Linux, other systems have other values
define('EINPROGRESS', 115);
function non_blocking_connect($host, $port, &$errno, &$errstr, $timeout) {
$ip = gethostbyname($host);
$s = socket_create(AF_INET, SOCK_STREAM, 0);
if (socket_set_nonblock($s)) {
$r = @socket_connect($s, $ip, $port);
if ($r || socket_last_error() == EINPROGRESS) {
$errno = EINPROGRESS; return $s;
}
}
$errno = socket_last_error($s);
$errstr = socket_strerror($errno);
socket_close($s);
return false;
}
?>

它运转的很好,然而在fsockopen(卡塔尔解析完hostname并且创立叁此中标的总是在此之前,扩展这段代码来保管大批量服务器将开销非常长日子。由此我们必得废弃这段代码;大家可以建设布局异步连接-不必要等待fsockopen再次来到连接景况。PHP如故供给解析hostname,可是将要展开二个总是之后马上回去,进而大家就能够三回九转下一台服务器。有二种情势能够完毕;PHP5中能够使用新添的stream_socket_client(卡塔尔(قطر‎函数直接调换掉fsocketopen(卡塔尔国。

现在用socket_select()替换掉stream_select(),用socket_read()替换掉fread(),用 socket_write()替换掉fwrite(),用socket_close(卡塔尔替换掉fclose(卡塔尔国就能够执行脚本了!
PHP5的Red Banner之处在于,你能够用stream_select(卡塔尔管理差不离全体的stream-比如您能够透过include STDIN用它选取键盘输入并保存进数组,你还足以吸收接纳通过proc_open(卡塔尔(قطر‎展开的管道中的数据。
若果您想让PHP4.3.x自身两全处理streams的效果与利益,我早已为你希图了二个让fsockopen能够异步专门的学业的patch。差异情使用该补丁, 该补丁不会产出在合法揭橥的PHP版本中,小编在补丁中附带了stream_socket_client(卡塔尔(قطر‎函数的兑现,通过它,你可以令你的脚本包容PHP5。

本文由威尼斯在线注册平台发布于威尼斯手机平台,转载请注明出处:假设你正在写一个基于多台服务器的php应用,假设你正在写一个基于多台服务器的php应用

上一篇:威尼斯手机平台PHP Frameworks大全 下一篇:没有了
猜你喜欢
热门排行
精彩图文