zoukankan      html  css  js  c++  java
  • php分享十一:PHP实现异步调用方法研究

    浏览器和服务器之间是通过 HTTP 协议进行连接通讯的。这是一种基于请求和响应模型的协议。浏览器通过 URL 向服务器发起请求,Web 服务器接收到请求,执行一段程序,然后做出响应,发送相应的html代码给客户端。

    有时服务器需要执行很耗时的操作,这个操作的结果并不需要返回给客户端。但因为php是同步执行的,所以客户端需要等待服务处理完才可以进行下一步。

    因此对于耗时的操作适合异步执行,服务器接收到请求后,处理完客户端需要的数据就返回,再异步在服务器执行耗时的操作。

    难点

    PHP没有真正实现多线程操作的方法。所以需要通过其它手段来进行模拟多线程。

    1.使用Ajax 与 img 标记

    原理,服务器返回的html中插入Ajax 代码或 img 标记,img的src为需要执行的程序。

    优点:实现简单,服务端无需执行任何调用

    缺点:在执行期间,浏览器会一直处于loading状态,因此这种方法并不算真正的异步调用。

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

     2.使用popen

    resource popen ( string $command , string $mode )

    pclose(popen('php /home/fdipzone/doRequest.php &', 'r')); 

    优点:执行速度快

    缺点:1.只能在本机执行

               2.不能传递大量参数

               3.访问量高时会创建很多进程。

    3.使用curl非阻塞调用

    设置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);  
        ?>  
    

     4.使用fsockopen

    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
    ";  
        $out .= "host:".$host."
    ";  
        $out .= "content-length:".strlen($query)."
    ";  
        $out .= "content-type:application/x-www-form-urlencoded
    ";  
        $out .= "connection:close
    
    ";  
        $out .= $query;  
      
        fputs($fp, $out);  
        fclose($fp);  
    }
    ?> 
    

     注意:

    1:当执行过程中,客户端连接断开或连接超时,都会有可能造成执行不完整,因此需要加上

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

    2:客户端短时间内多次调用a.php,出现部分请求 没有执行b.php 的情况。

    解决方法:
    在Nginx的nginx.conf文件中,查看worker_processes为1,判断服务端响应请求的线程启动限制太大,得知服务器本身配置为双核CPU,判断2-4线程比较合适,于是修改worker_processes为4.问题得到解决!
  • 相关阅读:
    C++ 虚函数表解析(转载)
    javaWeb中的/路径问题
    java创建多线程(转载)
    JSP中pageEncoding和charset区别,中文乱码解决方案(转载)
    Class.forName()的作用与使用总结(转载)
    Java内存模型
    java-锁膨胀的过程
    java对象头信息和三种锁的性能对比
    并发容器
    synchronized和volatile以及ReentrantLock
  • 原文地址:https://www.cnblogs.com/Alight/p/4971771.html
Copyright © 2011-2022 走看看