1. 程式人生 > >關於php語言限制,使用http協議不能及時返回客戶端方法解決方案

關於php語言限制,使用http協議不能及時返回客戶端方法解決方案

今天在公司,用php寫服務端的時候,因為專案中要做老師跟學生一對一輔導功能。然後學生上傳問題圖片之後在服務端找老師需要長時間的消耗,另外一個方面老師接收到學生的提問之後可能沒即時看到或者沒在電腦旁邊(我們在後臺指定老師10s的反應時間)我們會繼續找尋下一個老師。這樣的話客戶端請求到API層面,並沒有及時的返回結果,導致客戶端程式碼進入了一個類似死迴圈裡面,整個客戶端程式碼直接崩潰。
但是業務需要這樣,php又不能多執行緒,所以就考慮解決方案,最終選到了使用gearman。首先Gearman是一個用來把工作委派給其他機器、分散式的呼叫更適合做某項工作的機器、併發的做某項工作在多個呼叫間做負載均衡、或用來在呼叫其它語言的函式的系統。其他的東西,童鞋們可以google!
基於gearman可以直接安裝php擴充套件,這樣的話更方便一些,至於怎麼安裝擴充套件我就不一一介紹了,不對安裝的同學可以百度!
我來大概說一下gearman吧。它呢就是生產者和消費者的關係。至於生產者 你可以認為你的API層,或者是業務層面。如果你有一系列動作在服務端需要長時間的去做,甚至超出了php指令碼的有效執行時間。這個時候用到了gearman。你那個需要長時間執行的任務可以當作消費者放到gearman的任務佇列裡面去,api層面可以立即返回結果告訴客戶端請求成功。至於後續任務裡面如果有錯誤,或者其他提示的話 你可以用websocket或者你自己的容錯機制來官方的告訴客戶端提示使用者。好了說了這麼多上程式碼吧

    public function imgtoteacher(){
            $ret = array('err_no'=>1000,'err_msg'=>'system error');
            do{
                $must = array('subject_id','grade_id','url');
                $fields = array();
                $this->checkParams('post',$must,$fields);
                $user
= $this->checkUserSession(); $params = $this->params; $data = array( 'user_id'=>$user['id'], 'subject_id'=>$params['subject_id'], 'grade_id'=>$params['grade_id'], 'create_time'
=>time() ); $res = $this->wmodel->create_question($data); if($res){ $question_id = $res['id']; //插入詳情,問題圖片一律存問題詳情表 $detail = array( 'question_id'=>$question_id, 'img_url' =>$params['url'], 'create_time'=>time() ); $flag = $this->wmodel->insert_detail($detail); if(!$flag){ $ret = array('err_no'=>8002,'err_msg'=>'上傳問題圖片失敗,請重試!'); break; } //呼叫gearman掛起找老師的服務 $_array = array('question_id'=>$question_id,'subject_id'=>$params['subject_id'],'grade_id'=>$params['grade_id'],'img_url'=>$params['url'],'send_id'=>$user['id']); $client= new GearmanClient(); $client->addServer(); $client->doBackground("params", json_encode($_array)); //隨機選出老師詢問老師是否同意 // $single = $this->wmodel->select_teacher($params['subject_id'],$params['grade_id']); // if($single){ // //給線上的這個老師傳送socket請求詢問是否同意 // $post_data = array("type" => "publish", // "content" => array('type'=>1,'img_url'=>$params['url'],'student_id'=>$user['id'],'question_id'=>$question_id), // "to" => $single['user_id']); // $result = curlRequest($this->websocket_url,$post_data); // }else{ // $ret = array('err_no'=>8003,'err_msg'=>'暫無符合科目年級的線上老師,請詢問其他科目年級的問題!!'); // break; // } // if($result != 'ok'){ // $ret = array('err_no'=>8001,'err_msg'=>'websocket傳送通知失敗'); // break; // } $ret = array('err_no'=>0,'err_msg'=>'success'); break; //$ret = $this->sleep_select($question_id,$params['subject_id'],$params['grade_id'],$params['url']); }else{ $ret = array('err_no'=>8002,'err_msg'=>'上傳問題圖片失敗,請重試!'); break; } }while(0); $this->output($ret); }

我拿我我自己的程式碼給大家解釋。其中

$client= new GearmanClient();    
$client->addServer();
$client->doBackground("params", json_encode($_array));

這一段是連線gearman ,addserver那一點我沒寫是因為它自己預設的就是當前伺服器,這個我們可以認為是生產者。當然瞭如果你的消費者跟這個在同一個伺服器的話 那個地方你可以空著不填寫伺服器地址。至於client>doBackground("params",jsonencode(_array));這個地方尤其要注意那個引數一定要跟你的消費者保持一直第二個引數是你在消費者裡面需要用到的引數。
下面我們再來說消費者

<?php
//                   _ooOoo_  
//                  o8888888o  
//                  88" . "88  
//                  (| -_- |)  
//                  O\  =  /O  
//               ____/`---'\____  
//             .'  \\|     |//  `.  
//           /  \\|||  :  |||//  \  
//           /  _||||| -:- |||||-  \  
//           |   | \\\  -  /// |   |  
//           | \_|  ''\---/''  |   |  
//           \  .-\__  `-`  ___/-. /  
//         ___`. .'  /--.--\  `. . __  
//      ."" '<  `.___\_<|>_/___.'  >'"".  
//     | | :  `- \`.;`\ _ /`;.`/ - ` : | |  
//     \  \ `-.   \_ __\ /__ _/   .-` /  /  
//======`-.____`-.___\_____/___.-`____.-'======  
//                   `=---='  
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  
//佛祖保佑       永無BUG      心外無法       法外無心   永不修改 
  $worker= new GearmanWorker();
  $worker->addServer();     
  $worker->addFunction("params", "find_teacher");    
  while ($worker->work());

  function find_teacher($job)
  {
    //return ucwords(strtolower($job->workload()));
    $params = $job->workload();
    $params = json_decode($params,true);
    //這裡需要你寫一些業務處理
  }

上面就是消費者程式碼。使用$job->workload()接收你傳來的引數。然後你就可以寫你的業務邏輯,處理你需要長時間處理的業務。
已上就是解決了非同步處理任務的方法。具體gearman的一些引數和方法請訪問
http://php.net/manual/en/book.gearman.php

相關推薦

關於php語言限制使用http協議不能及時返回客戶方法解決方案

今天在公司,用php寫服務端的時候,因為專案中要做老師跟學生一對一輔導功能。然後學生上傳問題圖片之後在服務端找老師需要長時間的消耗,另外一個方面老師接收到學生的提問之後可能沒即時看到或者沒在電腦旁邊(我們在後臺指定老師10s的反應時間)我們會繼續找尋下一個老師。

TCP/IP協議HTTP協議

1、TCP TCP協議是一種面向連線的、 可靠的、基於位元組流的運輸層通訊協議。通過TCP協議傳輸,得到的是一個順序的無差錯的資料流。 三次握手        在TCP/IP協議中,TCP協議提供可靠的連線服務,連線是通過 三次握手進行初始化的。三

Android中的TCP/IP協議SocketHttp協議間的關係

前提:本片文章的名字叫做"Android開發中的TCP/IP協議,Socket程式設計",其實TCP/IP協議是一種網路協議,並不是在Android中才有的,也不只是在java中有,其他的開發語言中同樣也可以使用TCP/IP協議進行網路程式設計。之所以這麼說是因為在不久的以前

TCP/IP協議HTTP協議與webSocket協議區別

http協議(識別資料內容)與webSocket協議 同:建立在TCP之上,同http一樣通過TCP來傳輸資料 不同: HTTP協議為單向協議,即瀏覽器只能向伺服器請求資源,伺服器才能將資料傳送給瀏覽器,而伺服器不能主動向瀏覽器傳遞資料。分為長連線和短連線,短連線是

c語言socket使用http協議訪問apache伺服器

1、前言 簡單理解http協議,其實就是對傳送的資料進行了包裝(多了表示各種屬性的報頭) 2、環境 本人電腦配置了apache+php的開發環境,使用80埠 3、程式碼 client // ConnectToPHPServer.cpp : 定義控制檯應用程式的入口點。

基於STM32使用TCP/IPHTTP協議連線雲伺服器個人總結

對於如何將底層測量資料上傳到雲伺服器這個問題我進行了許多嘗試,都以失敗告終。這讓我不得不仔細去了解TCP/IP協議。OSI是網路程式設計的經典模型,將構成網路的程式分成了7個層面。TCP/IP是第三層與第四層。第一層,物理層:例如我要使用STM32驅動ESP8266連線路由器

Django之web應用/服務HTTP協議

一:web應用  web伺服器(本質是socket)都實現了wsgi協議; wsgi:web服務閘道器介面,是一個協議 cs和bs架構的軟體:s包括兩部分,web伺服器+application; 目前階段django專案用的web伺服器是:wsgiref+application,不支援併發;

[面試]常見TCP,UDPHTTP協議

1、OSI七層協議模型、2、TCP/IP四層模型、3、五層協議體系結構(OSI和TCP/IP的綜合)一、TCP協議與HTTP協議異同點1、TCP協議對應於傳輸層,而HTTP協議對應於應用層.2、Http協議是建立在TCP協議基礎之上的。當瀏覽器需要從伺服器獲取網頁資料的時候,

JavaWeb——B/S,C/S結構HTTP協議

B/S: 開發基於B/S結構專案:目前主要採用三種伺服器端語言:JSP,PHP,ASP.NET。 這三種語言構成三種常用應用開發組合:JSP+Oracle組合、PHP+MySQL體系、以及ASP.NET+SQL Server體系。 B/S 結構語言

java 解析http協議介面返回的json字串

String url = "http://114.119.10.14/younserver/authUserLogin.do?logintype=3&&username="+USERNAME+"&passwd="+PASSWORD;String st

【nginx】App打點場景下用nginx的log捕獲http協議的$request_body的正確方法

【應用場景】 App裡面的打點資料想自己收集,可以考慮向nginx發一個json,通過nginx生成的日誌實現實時獲取資料。 所以問題就歸結為nginx日誌的生成。 正如  http://www.cnblogs.com/meteorx/p/3188647.html 這篇作

HTTP協議04-返回狀態碼

authorize 處理 forbidden 常用 狀態碼 edi redirect post 緩存 狀態碼職責是在客戶端向服務器端發送請求時候,描述返回的請求結果。借助狀態碼,用戶可以知道服務器是否正常處理了請求,還是出錯了。 狀態碼的類別 類別

HTTP/3 竟然基於 UDPHTTP 協議這些年都經歷了啥?

聽到 HTTP/3 基於 UDP 協議的訊息,不少人可能都跟我一樣驚呆了。 我們從開始學習網路協議就一定會接觸到 HTTP,而教

mybatis 關聯查詢時從表只返回第一條記錄解決辦法

bean mod 第一條 solid ews 解決辦法 prop ica 元素 如果兩表聯查,主表和明細表的主鍵都是id的話,明細表的多條只能查詢出來第一條。 造成以上情況可能的

如何排查應用程序網關返回 HTTP Code 502 或客戶得到應用程序網關響應慢的問題(二)

ive and clas .cn 站點 https 完成 edi nag 問題描述 經過如何排查應用程序網關返回 HTTP Code 502 或客戶端得到應用程序網關響應慢的問題(一)中的排查步驟,可以判斷出是由於 Web 服務器自身問題導致的響應異常。 那麽可以在 IIS

HTTP協議中request報文請求方法和狀態響應碼

cti keep lang one com location 部分 AC url   一個HTTP請求報文由4部分組成: 請求行(request line) 請求頭部(header) 空行 請求數據   下圖給出了請求報文的一般格式:

人生苦短之HTTP協議及Requests庫的方法

資源 view 新的 path python進階 教程 區別 lock load requests庫的主要方法:requests.request()構造一個請求    requests.get()獲取HTML網頁的主要方法,對應於HTTP的GE

Ajax異步請求返回文件流(eg:導出文件時直接將導出數據用文件流的形式返回客戶客戶下載)

usermode table logs param onload img height tle http 在異步請求中要返回文件流,不能使用JQuery,因為$.ajax,$.post 不支持返回二進制文件流的類型,可以看到下圖,dataType只支持xml,json,sc

php版本過高tp5頁面出現No input file specified解決方案

一,php頁面出現No input file specified原因 (1)phpStudy配置php版本不符 (2)環境變數路徑不一致 二,解決方案: (1)切換相應版本即可 (2)修改tp5應用入口檔案同級目錄.htaccess檔案,內容如下: <IfModule mod_rewrit

C#.網路程式設計 Socket基礎(四) WPF系統Socket TCP協議 伺服器與客戶 不同型別檔案傳輸同時解決UI執行緒與工作執行緒的卡頓問題

一、簡介 雖然,本文的前面幾篇文章在WinForm中實現了Socket TCP協議 伺服器與客戶端 不同型別檔案傳輸,詳情見 但是,卻沒有在WPF中實現 Socket TCP協議 伺服器與客戶端 不同型別檔案傳輸。因此,本文將描述如何在WPF中實現該功能。