PHP異步請求之fsockopen()方法詳解

正常狀況下,PHP執行的都是同步請求,代碼自上而下依次執行,但有些場景如發送郵件、執行耗時任務等操做時就不適用於同步請求,只能使用異步處理請求。php

場景要求:

客戶端調用服務器a.php接口,須要執行一個長達10s-20s不等的耗資源操做,假如客戶端響應請求時間爲5秒(請求響應超時時間),5s以上無回覆即斷開鏈接。服務器

解決設想:

客戶端調用a.php以後,a.php執行異步多線程操做調用b.php,a.php調用成功後即刻反饋給客戶端回執,b.php自動執行耗資源操做。多線程

方案:

利用fsockopen()方法解決PHP異步請求app

1.封裝異步請求函數asyncRequest(),代碼以下:異步

/**
     * php異步請求
     * @param $host string 主機地址
     * @param $path string 路徑
     * @param $param array 請求參數
     * @return string
     */
    private static function asyncRequest($host, $path, $param = array()){

        $query = isset($param) ? http_build_query($param) : '';
        Bd_Log::debug($query);
        $port = 80;
        $errno = 0;
        $errstr = '';
        $timeout = 30; //鏈接超時時間(S)

        $fp = @fsockopen($host, $port, $errno, $errstr, $timeout);
        //$fp = stream_socket_client("tcp://".$host.":".$port, $errno, $errstr, $timeout);

        if (!$fp) {

            Bd_Log::debug('鏈接失敗');
            return '鏈接失敗';
        }
        if ($errno || !$fp) {

            Bd_Log::debug($errstr);
            return $errstr;
        }

        stream_set_blocking($fp,0); //非阻塞
        stream_set_timeout($fp, 1);//響應超時時間(S)
        $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;

        $result = @fputs($fp, $out);

        @fclose($fp);
        return $result;

    }

實例:

正常接口a.php,以下socket

    /**
     * 正常接口a.php
     * @param $host string 主機地址
     * @param $path string 路徑
     * @param $param array 請求參數
    */
  public function a(){
       $param = array(
           'XXX' => $XXX,
        );
        $asyncData = $this->asyncRequest( $host, $path ,$param);

        echo'a.php success'      
  }

耗時接口b.php,以下async

    /**
     * 耗時接口b.php,依次輸出三種結果
    */
    public function b(){
    
      set_time_limit(0);
        ignore_user_abort(true);//設置與客戶機斷開是否會終止執行
        fastcgi_finish_request();//提升請求的處理速度
  
        sleep(30);
        echo "耗時30秒";

        sleep(20);
        echo "耗時20秒";

        sleep(10);
        echo "耗時10秒";
    }

 

上述實例即爲簡單的測試接口部分代碼,根據本身需求作修改便可;tcp

相關文章
相關標籤/搜索