百分百源码网-让建站变得如此简单! 登录 注册 签到领金币!

主页 | 如何升级VIP | TAG标签

当前位置: 主页>网站教程>网页制作> 详解 PHP 异步后台处置
分享文章到:

详解 PHP 异步后台处置

发布时间:12/01 来源:未知 浏览: 关键词:

PHP 异步后台处置

PHP 作为后台的接口效劳器已经很常见,在实际利用场景中经常需要异步后台处置。

引荐:《PHP视频教程》

PHP 当然具有它能作为后台效劳器的优势之处,但是,在处置一些客户端并不关怀的结果时,就显出它的弊端了,没有异步施行的机制。

就比方我们想做一些关于某次客户端拜访php的机能记载(包罗开端时间、完毕时间、此次结果状态等)的记载时,客户端当然想的是php的本次处置能够早点返回,拿到结果,而假如安置常规的方案,客户端就得等php做完机能记载之后,才能拿到结果。

相当于你去银行去查你此刻的余额,而柜员跑过去跟其别人闹了一会儿的磕,在来告诉你的结果一样。

所以,许多时候,就需要一种php能施行异步操纵。

PHP 怎样实现异步处置呢?

其中一种方案就是利用php的系统调取,开启新的进程来实现。

php 供给了fsockopen函数,此函数的功效为初始化一个套接字连接到指定主机,默许状况下将以堵塞模式开启套接字连接。

当然你可以通过stream_set_blocking()将它转换到非堵塞模式。这是关键。

所以,思绪就是:开启一个非堵塞的套接字连接到本机,本机收到之后作一些耗时处置。

相似这样的处置代码(文件posttest.php):

$fp = fsockopen($php_Path,80);
if (!$fp) {
    LMLog::error("fsockopen:err" );
} else {
    $out = "GET /album/action/album_write_friends_thread_record.php?key=&u=   HTTP/1.1\r\n";
    $out .= "Host: ".$php_Path."\r\n";
    $out .= "Connection: Close\r\n\r\n";
    stream_set_blocking($fp,true);
    stream_set_timeout($fp,1);
    fwrite($fp, $out);
    usleep(1000);
    fclose($fp);
}

这里,usleep(1000) 非常关键,它能包管这个恳求能发出去。

我们在来看处置的代码逻辑(文件album_write_friends_thread_record.php):

<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2016-09-23
 * Time: 09:26
 */
/**
 * 客户端调取效劳器接口页面
 * user: guwen
 */
sleep(20);// 睡眠20s
?>

实际上,我们效劳器在施行fsockopen 那段程序时,就不会再等20s之后才能返回给客户端,

而是发出这个恳求之后,即返回客户端,烧毁进程,而把剩余的工作交由其他进程渐渐做去,这就实现了php的异步。

PHP 异步施行的4种常用方式

客户端与效劳器端是通过HTTP和谈停止连接通讯,客户端发起恳求,效劳器端接收到恳求后施行处置,并返回处置结果。

有时效劳器需要施行很耗时的操纵,如处置下载、新闻下发、邮件发送等,这个操纵的结果并不需要返回给客户端。

但由于php是同步施行的,所以客户端需要等候效劳处置完才可以停止下一步。

因此,关于耗时的操纵适合异步施行,效劳器接收到恳求后,处置完客户端需要的数据就先返回,剩余耗时的操纵再异步在效劳器后台施行。

PHP异步施行的常用方式常见的有以下几种,可以按照各自优缺陷停止选中:

1. ajax 恳求

客户端页面采纳AJAX技术恳求效劳器

$.get("doRequest.php", { name: "fdipzone"} );
<img src="doRequest.php?name=fdipzone">

长处:最简便,也最快,就是在返回给客户端的HTML代码中,嵌入AJAX调取,或者,嵌入一个img标签,src指向要施行的耗时足本。

缺陷:一样来说Ajax都应当在onLoad今后触发,也就是说,会员点开页面后,就关闭,那就不会触发我们的后台足本了。

而使用img标签的话,这种方式不克不及称为严厉意义上的异步施行。会员阅读器会长时间等候php足本的施行完成,也就是会员阅读器的状态栏不断显示还在load。

当然,还可以使用其他的相似道理的办法,比方script标签等等。

2. popen()函数

该函数翻开一个指向进程的管道,该进程由派生给定的 command 命令施行而发生。

翻开一个指向进程的管道,该进程由派生给定的 command 命令施行而发生。

所以可以通过调取它,但忽略它的输出。使用代码如下:

// popen — 翻开进程文件指针  
resource popen ( string $command , string $mode )
pclose(popen('php /home/fdipzone/doRequest.php &', 'r'));

长处:幸免了第一个办法的缺陷,并且施行速度快。

缺陷:这种办法不克不及通过HTTP和谈恳求别的的一个WebService,只能施行当地的足本文件。并且只能单向翻开,没法穿大量参数给被调取足本。并且假如,拜访量很高的时候,会发生大量的进程。假如使用到了外部资源,还要本人思考竞争。

1)只能在本机施行

2)不克不及传递大量参数

3)拜访量高时会创立许多进程

3. curl 扩展

CURL是一个强大的HTTP命令行工具,可以模拟POST/GET等HTTP恳求,然后得到和提取数据,显示在"标准输出"(stdout)上面。

设定curl的超不时间 CURLOPT_TIMEOUT 为1 (最小为1),因此客户端需要等候1秒

代码如下:

<?php 
    $ch = curl_init(); 
    $curl_opt = array( 
      CURLOPT_URL, 'http://www.example.com/doRequest.php'
      CURLOPT_RETURNTRANSFER,1, 
      CURLOPT_TIMEOUT,1 
    ); 
    curl_setopt_array($ch, $curl_opt); 
    curl_exec($ch); 
    curl_close($ch); 
?>

缺陷:如你问题中描写的一样,由于使用CURL需要设定CUROPT_TIMEOUT为1(最小为1,愁闷)。也就是说,客户端至少必需等候1秒钟。

4. fscokopen()函数

fsockopen是最好的,缺陷是需要本人拼接header部分。

<?php 
    $url = 'http://www.example.com/doRequest.php'; 
    $param = array( 
      'name'=>'fdipzone', 
      'gender'=>'male', 
      'age'=>30 
    ); 
         
    doRequest($url, $param); 
         
    function doRequest($url, $param=array()){ 
        $urlinfo = parse_url($url); 
 
        $host = $urlinfo['host']; 
        $path = $urlinfo['path']; 
        $query = isset($param)? http_build_query($param) : ''; 
 
        $port = 80; 
        $errno = 0; 
        $errstr = ''; 
        $timeout = 10; 
 
        $fp = fsockopen($host, $port, $errno, $errstr, $timeout); 
 
        $out = "POST ".$path." HTTP/1.1\r\n"; 
        $out .= "host:".$host."\r\n"; 
        $out .= "content-length:".strlen($query)."\r\n"; 
        $out .= "content-type:application/x-www-form-urlencoded\r\n"; 
        $out .= "connection:close\r\n\r\n"; 
        $out .= $query; 
 
        fputs($fp, $out); 
        fclose($fp); 
    } 
?>

留意:当施行历程中,客户端连接断开或连接超时,都会有大概造成施行不完全,因此需要加上

ignore_user_abort(true); // 忽略客户端断开 
set_time_limit(0);    // 设定施行不超时

fsockopen支撑socket编程,可以使用fsockopen实现邮件发送等socket程序等等,使用fcockopen需要本人手动拼接出header部分

可以参照 : http://cn.php.net/fsockopen/

使用示例如下:

$fp = fsockopen("www.34ways.com", 80, $errno, $errstr, 30);
if (!$fp) {
    echo "$errstr ($errno)<br />\n";
} else {
    $out = "GET /index.php  / HTTP/1.1\r\n";
    $out .= "Host: www.34ways.com\r\n";
    $out .= "Connection: Close\r\n\r\n";
   
    fwrite($fp, $out);
    /*忽略施行结果
    while (!feof($fp)) {
        echo fgets($fp, 128);
    }*/
    fclose($fp);
}

所以总结来说,fscokopen()函数应当可以知足您的要求。可以尝试一下。

fscokopen的问题和popen 一样,并发非常多时会发生许多子进程,当到达apache的连接限制数时,就会挂掉,我问题已经说了这种状况。

PHP 本身没有多线程的东西,但可以曲线的方法来培养出一样的结果,比方多进程的方式来到达异步调取,只限于命令模式。还有一种更简便的方式,可用于 Web 程序中,那就是用fsockopen()、fputs() 来恳求一个 URL 而无需等候返回,假如你在阿谁被恳求的页面中做些事情就相当于异步了。  

关键代码如下:

$fp=fsockopen('localhost',80,&$errno,&$errstr,5);
if(!$fp){
    echo "$errstr ($errno)<br />\n";
}
fputs($fp,"GET another_page.php?flag=1\r\n");
fclose($fp);

上面的代码向页面 another_page.php 发送完恳求就不管了,用不着等候恳求页面的响应数据,利用这一点就可以在被恳求的页面 another_page.php 中异步的做些事情了。

比方,一个很切实的利用,某个 Blog 在每 Post 了一篇新日志后需要给所有它的订阅者发个邮件通知。假如依照平常的方式就是:

日志写完 -> 点提交按钮 -> 日志插入到数据库 -> 发送邮件通知 ->

告知撰写者公布成功

那么作者在点提交按钮到看到成功提醒之间大概会等候很常时间,根本是在等邮件发送的历程,比方连接邮件效劳非常、或器迟缓或是订阅者太多。而实际上是不管邮件发送成功与否,包管日志留存成功根本可接受的,所以等候邮件发送的历程是很不经济的,这个历程可异步来施行,并且邮件发送的结果不太关怀或以日志情势记载备查。

改善后的流程就是:

日志写完 -> 点提交按钮 -> 日志插入到数据库 --->

告知撰写者公布成功

└ 发送邮件通知 -> [记下日志]

用个实际的程序来测试一下,有两个 php,离别是 write.php 和 sendmail.php,在 sendmail.php 用 sleep(seconds) 来模拟程序施行使用时间。

write.php,施行耗时 1 秒

<?php 
    function asyn_sendmail() {
        $fp=fsockopen('localhost',80,&$errno,&$errstr,5);
        if(!$fp){
            echo "$errstr ($errno)<br />\n";
        }
        sleep(1);
        fputs($fp,"GET /sendmail.php?param=1\r\n"); #恳求的资源 URL 必然要写对
        fclose($fp);
    } 
      
    echo time().'<br>';
    echo 'call asyn_sendmail<br>';
    asyn_sendmail();
    echo time().'<br>';
    ?>

sendmail.php,施行耗时 10 秒

<?php
    //sendmail();
    //sleep 10 seconds
    sleep(10);
    fopen('C:\'.time(),'w');
?>

通过页面拜访 write.php,页面输出:

1272472697 call asyn_sendmail
1272472698

并且在 C:\ 生成文件:

1272472708

从上面的结果可知 sendmail.php 花费至少 10 秒,但不会堵塞到 write.php 的连续往下施行,表白这一历程是异步的。

以上就是详解 PHP 异步后台处置的具体内容,更多请关注百分百源码网其它相关文章!

打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

百分百源码网 建议打赏1~10元,土豪随意,感谢您的阅读!

共有151人阅读,期待你的评论!发表评论
昵称: 网址: 验证码: 点击我更换图片
最新评论

本文标签

广告赞助

能出一分力是一分吧!

订阅获得更多模板

本文标签

广告赞助

订阅获得更多模板