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.问题得到解决!
  • 相关阅读:
    Maven关于web.xml中Servlet和Servlet映射的问题
    intellij idea的Maven项目运行报程序包找不到的错误
    修改Maven项目默认JDK版本
    刷题15. 3Sum
    刷题11. Container With Most Water
    刷题10. Regular Expression Matching
    刷题5. Longest Palindromic Substring
    刷题4. Median of Two Sorted Arrays
    刷题3. Longest Substring Without Repeating Characters
    刷题2. Add Two Numbers
  • 原文地址:https://www.cnblogs.com/Alight/p/4971771.html
Copyright © 2011-2022 走看看