本文僅做爲本人學習過程當中的一點心得,歡迎你們拍磚。php
PHP從主流來看,是一門面向過程的語言,它的最大缺點就是沒法實現多線程管理,其程序的執行都是從頭至尾,按照邏輯一路執行下來,不可能出現分支,這一點是限制php在主流程序語言中往更高級的語言發展的緣由之一。nginx
在PHP中咱們有的時候其實但願在執行某項操做的時候,同時去執行另一項操做,舉一個場景:在用戶搶票的時候,你並不但願用戶排隊去鏈接數據庫進行查詢、判斷、插入,完成以後再返回用戶結果。其實咱們並不須要用戶等那麼久的時間,用戶提交以後,直接告訴他已經搶票成功了就能夠了,至於各類操做,交給後臺去處理就好。固然,這種狀況咱們如今都用消息列表來處理,把每個用戶提交的請求存在一個消息列隊中,告訴用戶已經搞定了,用戶愉快的關掉頁面以後,實際上後臺還在一個一個從消息列隊中取出請求進行操做。咱們這篇文章則是經過一種異類的手法,實現操做在後臺運行,無需用戶等待。數據庫
首先,咱們要建立一個請求入口:服務器
<?php 提交的數據 提交給後臺 告訴用戶已經搞定了
其次,咱們須要一個後臺處理程序,用戶是否在線並不影響它的運行:多線程
<?php ignore_user_abort(true); set_time_limit(0); 過來的數據 數據處理
如今的問題是,在第一段代碼中,如何「提交給後臺」?咱們經過一種非阻塞式的請求來實現這個功能。也就是建立一個能夠被訪問的url,在這個url運行第二段程序,經過一個請求來請求這個url,從而激活第二段程序自動運行。接下來咱們直接看代碼:curl
// 遠程請求(不獲取內容)函數 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); } }
咱們建立了一個基於fsockopen的函數,這個函數中利用fsockopen去訪問url,可是在訪問時,並不要求獲取url顯示的內容,而是僅僅發出訪問請求,請求到達後立刻關閉這個訪問。這樣作的好處就是無需再等待被訪問的url是否返回了可靠的信息,節約了時間,這段代碼的執行時間在0.1-0.2秒之間,對於普通訪客而言,幾乎察覺不到。所以,在使用時,僅須要調用這個函數和對應的url便可。不過,這裏並無提供數據傳輸的部分,如何傳輸數據,其實只須要在$header中增長post的內容便可。函數
除了fsockopen,curl其實也能夠實現這樣的效果,有些主機上並不支持fsockopen,咱們就能夠使用curl來實現。post
function _curl($url) { $ch = curl_init(); curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); curl_setopt($ch,CURLOPT_TIMEOUT,1); $result = curl_exec($ch); curl_close($ch); return $result; }
這段代碼的關鍵是提供了一個Timeout,僅1秒鐘,也就是說curl發出請求,不管是否接收到返回的內容,1秒鐘以後都會關閉該訪問,所以這個函數的執行數據爲1.0-1.1秒之間。但對於用戶來講,若是是一個須要進行數據處理的應用,1秒中的等待幾乎是被忽略的,若是你但願用一段更簡單和容易被理解的代碼,能夠選擇curl來實現。學習