php定時計劃任務與fsockopen持續進程執行個體_php技巧

來源:互聯網
上載者:User

Web伺服器執行一個PHP指令碼,有時耗時很長才能返回執行結果,後面的指令碼需要等待很長一段時間才能繼續執行。
如果想實現只簡單觸發耗時指令碼的執行而不等待執行結果就直接執行下一步操作,可以通過fscokopen函數來實現。

PHP支援socket編程,fscokopen函數返回一個到遠程主機串連的控制代碼,可以像使用fopen返回的控制代碼一樣,對它進行 fwrite、fgets、fread等操作。
使用fsockopen串連到本機伺服器,觸發指令碼執行,然後立即返回,不等待指令碼執行完成,即可實現非同步 執行PHP的效果。

例子:

複製代碼 代碼如下:

<? 
function triggerRequest($url, $post_data = array(), $cookie = array()){ 
  $method = "GET";  //通過POST或者GET傳遞一些參數給要觸發的指令碼 
  $url_array = parse_url($url); //擷取URL資訊 
  $port = isset($url_array['port'])? $url_array['port'] : 80;   
  $fp = fsockopen($url_array['host'], $port, $errno, $errstr, 30); 
  if (!$fp) { 
    return FALSE; 
  } 
  $getPath = $url_array['path'] ."?". $url_array['query']; 
  if(!empty($post_data)){ 
    $method = "POST"; 
  } 
  $header = $method . " " . $getPath; 
  $header .= " HTTP/1.1\r\n"; 
  $header .= "Host: ". $url_array['host'] . "\r\n "; //HTTP 1.1 Host域不能省略 
  /*以下頭資訊域可以省略
  $header .= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13 \r\n";
  $header .= "Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,q=0.5 \r\n";
  $header .= "Accept-Language: en-us,en;q=0.5 ";
  $header .= "Accept-Encoding: gzip,deflate\r\n";
   */ 

  $header .= "Connection:Close\r\n"; 
  if(!empty($cookie)){ 
    $_cookie = strval(NULL); 
    foreach($cookie as $k => $v){ 
$_cookie .= $k."=".$v."; "; 
    } 
    $cookie_str =  "Cookie: " . base64_encode($_cookie) ." \r\n"; //傳遞Cookie 
    $header .= $cookie_str; 
  } 
  if(!empty($post_data)){ 
    $_post = strval(NULL); 
    foreach($post_data as $k => $v){ 
$_post .= $k."=".$v."&"; 
    } 
    $post_str  = "Content-Type: application/x-www-form-urlencoded\r\n";  
    $post_str .= "Content-Length: ". strlen($_post) ." \r\n"; //POST資料的長度 
    $post_str .= $_post."\r\n\r\n "; //傳遞POST資料 
    $header .= $post_str; 
  } 
  fwrite($fp, $header); 
  //echo fread($fp, 1024); //伺服器返回 
  fclose($fp); 
  return true; 
}  

這樣就可以通過fsockopen()函數來觸發一個PHP指令碼的執行,然後函數就會返回。 接著執行下一步操作了。
現在存在一個問題:當用戶端中斷連線後,也就是triggerRequest發送請求後,立即關閉了串連,那麼可能會引起伺服器端正在執行的指令碼退出

在 PHP 內部,系統維護著串連狀態,其狀態有三種可能的情況:

* 0 – NORMAL(正常)
* 1 – ABORTED(異常退出)
* 2 – TIMEOUT(逾時)

  當 PHP 指令碼正常地運行 NORMAL 狀態時,串連為有效。當用戶端中斷串連時,ABORTED 狀態的標記將會被開啟。遠程用戶端串連的中斷通常是由使用者點擊 STOP 按鈕導致的。當連線時間超過 PHP 的時限(參閱 set_time_limit() 函數)時,TIMEOUT 狀態的標記將被開啟。

可以決定指令碼是否需要在用戶端中斷串連時退出。有時候讓指令碼完整地運行會帶來很多方便,即使沒有遠程瀏覽器接受指令碼的輸出。預設的情況是當遠程用戶端 串連 中斷時指令碼將會退出。該處理過程可由 php.ini 的 ignore_user_abort 或由 Apache .conf 設定中對應的"php_value ignore_user_abort"以及 ignore_user_abort() 函數來控制。如果沒有告訴 PHP忽略使用者的中斷,指令碼將會被中斷,除非通過 register_shutdown_function() ,可以讓我們設定一個當執行關閉時可以被調用的另一個函數.也就是說當我們的指令碼執行完成或意外死掉導致PHP執行即將關閉時,我們的這個函數將會 被調用,當遠端使用者點擊 STOP 按鈕後,指令碼再次嘗試輸出資料時,PHP 將會檢測到串連已被中斷,並調用關閉觸發函數。

  指令碼也有可能被內建的指令碼計時器中斷。預設的逾時限制為 30 秒。這個值可以通過設定 php.ini 的 max_execution_time 或 Apache .conf 設定中對應的"php_value max_execution_time"參數或者 set_time_limit() 函數來更改。當計數器逾時的時候,指令碼將會類似於以上串連中斷的情況退出,先前被註冊過的關閉觸發函數也將在這時被執行。在該關閉觸發函數中,可以通過調 用 connection_status() 函數來檢查逾時是否導致關閉觸發函數被調用。如果逾時導致了關閉觸發函數的調用,該函數將返回 2。

  注意,ABORTED 和 TIMEOUT 狀態可以同時有效。這在告訴 PHP 忽略使用者的退出操作時是可能的。PHP 將仍然注意使用者已經中斷了串連但指令碼仍然在啟動並執行情況。如果到了啟動並執行時間限制,指令碼將被退出,設定過的關閉觸發函數也將被執行。在這時會發現函數 connection_status() 返回 3。

所以還在要觸發的指令碼中指明:

複製代碼 代碼如下:

<?php 
  ignore_user_abort(TRUE); //如果用戶端中斷連線,不會引起指令碼abort 
  set_time_limit(0); //取消指令碼執行延時上限 
或使用:
<?php 
  register_shutdown_function(callback fuction[, parameters]); //註冊指令碼退出時執行的函數

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.