• 转:PHP非阻塞模式


    你可以任意转摘“PHP非阻塞模式”,但请保留本文出处和版权信息。
    作者:尘缘,QQ:130775,来源:http://www.4wei.cn/archives/1002336

    让PHP不再阻塞当PHP作为后端处理需要完成一些长时间处理,为了快速响应页面请求,不作结果返回判断的情况下,可以有如下措施:

    一、若你使用的是FastCGI模式,使用fastcgi_finish_request()能马上结束会话,但PHP线程继续在跑。

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    echo "program start.";
     
    file_put_contents('log.txt','start-time:'.date('Y-m-d H:i:s'), FILE_APPEND);
    fastcgi_finish_request();
    sleep(1);
    echo 'debug...';
    file_put_contents('log.txt', 'start-proceed:'.date('Y-m-d H:i:s'), FILE_APPEND);
     
    sleep(10);
    file_put_contents('log.txt', 'end-time:'.date('Y-m-d H:i:s'), FILE_APPEND);

    这个例子输出结果可看到输出program start.后会话就返回了,所以debug那个输出浏览器是接收不到的,而log.txt文件能完整接收到三个完成时间。

    二、使用fsockopen、cUrl的非阻塞模式请求另外的网址

    1
    2
    3
    4
    5
    6
    7
    8
    $fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
    if (!$fp) die('error fsockopen');
    stream_set_blocking($fp,0);
    $http = "GET /save.php  / HTTP/1.1 ";   
    $http .= "Host: www.example.com ";   
    $http .= "Connection: Close ";
    fwrite($fp,$http);
    fclose($fp);

    利用cURL中的curl_multi_*函数发送异步请求

    1
    2
    3
    4
    5
    6
    $cmh = curl_multi_init();
    $ch1 = curl_init();
    curl_setopt($ch1, CURLOPT_URL, "http://localhost:6666/child.php");
    curl_multi_add_handle($cmh, $ch1);
    curl_multi_exec($cmh, $active);
    echo "End ";

    三、使用Gearman、Swoole扩展
    Gearman是一个具有php扩展的分布式异步处理框架,能处理大批量异步任务;
    Swoole最近很火,有很多异步方法,使用简单。(尘缘注:号称重新定义PHP,把NodeJS喷得体无完肤。Swoole工具虽好,却感觉是扩展本身跟NodeJS没可比性)

    四、使用redis等缓存、队列,将数据写入缓存,使用后台计划任务实现数据异步处理。
    这个方法在常见的大流量架构中应该很常见吧

    五、极端的情况下,可以调用系统命令,可以将数据传给后台任务执行,个人感觉不是很高效。

    1
    2
    $cmd = 'nohup php ./processd.php $someVar >/dev/null  &';
    `$cmd`

    六、外国佬的大招,没看懂,php原生支持

    http://nikic.github.io/2012/12/22/Cooperative-multitasking-using-coroutines-in-PHP.html

    七、安装pcntl扩展,使用pcntl_fork生成子进程异步执行任务,个人觉得是最方便的,但也容易出现zombie process。

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    if (($pid = pcntl_fork()) == 0) {
        child_func();    //子进程函数,主进程运行
    } else {
        father_func();   //主进程函数
    }
     
    echo "Process " . getmypid() . " get to the end. ";
     
    function father_func() {
        echo "Father pid is " . getmypid() . " ";
    }
     
    function child_func() {
        sleep(6);
        echo "Child process exit pid is " . getmypid() . " ";
        exit(0);
    }
  • 相关阅读:
    部署 AppGlobalResources 到 SharePoint 2010
    还原一个已删除的网站集
    使用仪表板设计器配置级联筛选器 (SharePoint Server 2010 SP1)
    File or arguments not valid for site template
    Pex and Moles Documentation
    Content Query Webpart匿名访问
    Running Moles using NUnit Console from Visual Studio
    Calling a WCF Service using jQuery in SharePoint the correct way
    Updating Content Types and Site Columns That Were Deployed as a Feature
    asp.net中判断传过来的字符串不为空的代码
  • 原文地址:https://www.cnblogs.com/guoyongrong/p/4078681.html
Copyright © 2020-2023  润新知