工作中php處理HTTP請求的缺陷總結


之前遇到過php在處理一部分業務的時候總是感覺有短板,有些東西總是不能隨人心意。比如執行時間問題,一個進程需要讀取多條數據放入數組循環執行處理流程,就會很慢,容易超時,這個超時問題 可以用php設置set_time_limit(0);來解決,但是仍然感覺有點不合理。有些時候如果不需要拿到返回結果還好,如果需要得到返回結果,這個超時成504就給人很不好的體驗。

后來我想到采用一個進程來處理返回數據給http,另起一個curl去處理那些時間很長很復雜的業務,但是這樣的話 就會curl一直等待着新請求直到結束。直到我發現 curl可以設置超時時間,就解決了這邊的問題,讓用戶先感受到 請求已經結束,然后后面的進程實際上在暗中執行,前台中如果用戶需要看到執行效果,可以設置一個提示正在處理中,避免他看到數據還沒有處理完成的尷尬。

這樣的業務出現很多次了,在之前做同步粉絲信息的時候就遇到過。幾萬個粉絲需要同步下來信息,30秒的超時顯然是不夠的,就需要提前返回處理信息給用戶才行。

還有一次是需要調用別人的接口的業務,本來用戶不關心調接口的那個業務,請求可以很快結束掉的,但是調用接口這一步等待時間過久,就會造成前端卡頓體驗效果不大好這樣的損失,給業務的處理帶來很頭疼的不必要的性能損失。

解決方案出現:

采用異步交互

在采用異步交互的時候,需要把你要處理的業務先放入一個隊列,然后立即返回成功,這樣前面用戶就不會出現等待卡死的問題。那么問題來了,如何讓隊列里面的任務自動執行呢?

這里還是推薦使用定時腳本去跑一下,根據合適的數據量 設定腳本運行時間間隔為多久。

當然如果不采用異步的話 有地方如果用戶不關心返回結果可以采用同步,但是有的業務要求超時時間很短,就需要設置超時時間為毫秒級,如何設置呢?請看我的另一篇文章

http://www.cnblogs.com/lizhaoyao/p/5640887.html

當然 除了能在curl控制超時時間外我們還可以通過fsocket異步訪問來獲取數據。

例如 訪問這個

<?php

// 遠程請求(不獲取內容)函數,下面可以反復使用
function _sock($url) {
  $host = parse_url($url,PHP_URL_HOST);
  $port = parse_url($url,PHP_URL_PORT);
  $port = $port ? $port : 80;
  $scheme = parse_url($url,PHP_URL_SCHEME);
  $path = parse_url($url,PHP_URL_PATH);
  $query = parse_url($url,PHP_URL_QUERY);
  if($query) $path .= '?'.$query;
  if($scheme == 'https') {
    $host = 'ssl://'.$host;
  }

  $fp = fsockopen($host,$port,$error_code,$error_msg,1);
  if(!$fp) {
    return array('error_code' => $error_code,'error_msg' => $error_msg);
  }
  else {
    stream_set_blocking($fp,true);//開啟了手冊上說的非阻塞模式
    stream_set_timeout($fp,1);//設置超時
    $header = "GET $path HTTP/1.1\r\n";
    $header.="Host: $host\r\n";
    $header.="Connection: close\r\n\r\n";//長連接關閉
    fwrite($fp, $header);
    usleep(1000); // 這一句也是關鍵,如果沒有這延時,可能在nginx服務器上就無法執行成功
    fclose($fp);
    return array('error_code' => 0);
  }
}

_sock('http://localhost/php_file/file.php');

echo "after fsocket";

然后在這個 localhost 下面的 php_file 里面的file.php里面寫一個循環創建文件的代碼 每秒鍾創建一個文件

 

<?php
$act = isset($_GET['act']) ? $_GET['act'] : "";

$i=100;

while ($i<200) {
    $i++;
    $file_name = $i . "_data.txt";
    if ($act == '') {
        sleep(1);
        file_put_contents($file_name, date("Y-m-d H:i:s",time()));
    }
    elseif ($act == 'del') {
        unlink($file_name);
    }
}

之后執行 fsocket 的代碼

迅速打印了 “after fsocket“

然后你就看到那個 101_data.txt 到 200_data.txt 在逐漸生成了

 

 那么讓那段耗時的代碼自己在后面慢慢執行的效果就達到了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM