php 使用fsockopen 發送http請求


需求背景

在公司開發這么一個需求,每天三次定時催付待客服催付狀態的訂單,設定每天15、16、17點三次執行job任務來給一批訂單打電話催付,需要三個時間點都把待客服催付的訂單撥打一遍電話,根據數據組統計,大概每天需要催付的訂單數量在6000左右,對接第三方電話呼叫業務,拿到訂單信息來呼叫。

測試狀態

拿500個訂單手動執行第一波測試,發現500個訂單催付完畢需要30多分鍾,那么6000個訂單按照需求催付時間點是完全不夠的,半小時500個,一小時最多1000個。

初步排查,是由於使用php  curl請求導致每一次遍歷的請求時間慢,由於curl請求最短的time時間耗時是1秒,那么一小時3600秒也是不夠呼完這6000單。

解決方案

一、在遍歷循環的時候把每次請求的量丟入消費系統(隊列),然后根據開啟多個消費者來消費這些(上線迫在眉睫,來不及)

二、有沒有類似curl更快的方案,發現了fsockopen,按照使用方法配置完500個訂單,遍歷完成只需要18秒。

需求代碼

  /** * 通過訂單信息組裝呼叫信息 * @param array $order * @return array */
    private function getCallInfoByOrder ($order = []) { $order_ext = OrderExt::model()->getPrimary($order['order_id']); $point = (isset($order_ext['app_ver'])&&version_compare($order_ext['app_ver'],Tools::PRICE_COMPARE_VERSION,">=")); $pay_detail = json_decode($order['pay_detail'], true); $call_text = OrderPayRemainService::organizeHeLiText($order['create_time'], $pay_detail['cash'], $point); return ['phone' => $order['phone'], 'call_text' => $call_text]; } //開始呼叫
    private function toCall ($call_info) { $params = $this->formatGetParams($call_info); EdjLog::info(__METHOD__ .'he li to call info' . json_encode($call_info)); $this->doCurlGetRequest(self::CALL_API_URL, $params, $call_info); } //撥號請求
    private function doCurlGetRequest($url, $data = [],  $call_info = []){ if($url == "" || empty($data)){ return false; } $response = $this->fsockopen_request($url,$data); // $response_arr = explode("\r\n", $response); //
// if (in_array(self::TOOKEN_INVALID,$response_arr)) { // EdjLog::info(__METHOD__ .'he li accessToken expire' . json_encode($call_info)); // $this->redis->del(self::ACCESS_TONEN_CACHE_KEY); // $this->toCall($call_info); // } $response_arr = explode("\r\n", $response);

        return true; }
 private function fsockopen_request($URL,$data, $referrer="") {
EdjLog::info(__METHOD__ .'he li request url:' . $URL.'-data:'.json_encode($data));
$URL_Info = parse_url($URL);
foreach($data as $key=>$value)
$values[] = "$key=" . urlencode($value);
$data_string = implode("&",$values);
if(!isset($URL_Info["port"]))
$URL_Info["port"] = 80;
$request = '';
$request.="POST ".$URL_Info["path"]." HTTP/1.1\n";
$request.="Host: ".$URL_Info["host"]."\n";
$request.="Referer: $referrer\n";
$request.="Content-type: application/x-www-form-urlencoded\n";
$request.="Content-length: ".strlen($data_string)."\n";
$request.="Connection: close\n";
$request.="\n";
$request.=$data_string."\n";

$fp = fsockopen($URL_Info["host"],$URL_Info["port"],$errno, $errstr);
if (!$fp) {
EdjLog::info('socket_open error:'.json_encode($data). "Error: $errstr ($errno)");
} else {
stream_set_blocking($fp, true);//開啟了非阻塞模式
fputs($fp, $request);
fclose($fp);
usleep(400000); //等待500ms
EdjLog::info('socket_open success:'.json_encode($data));
}
// $result = '';
// while(!feof($fp)) {
//
// $response = fgets($fp, 512);
// if (!is_numeric(trim($response))) {
// continue;
// }
// $result.= $response;
// }

// return $result;
}
 
        

完整說明

<?php $srv_ip = '192.168.1.5';//你的目標服務地址. 
  $srv_port = 80;//端口 
  $url = 'http://localhost/fsock.php'; //接收你post的URL具體地址 
  $fp = ''; $errno = 0;//錯誤處理 
  $errstr = '';//錯誤處理 
  $timeout = 10;//多久沒有連上就中斷 
  $post_str = "username=demo&password=hahaha";//要提交的內容. //打開網絡的 Socket 鏈接。 
  $fp = fsockopen($srv_ip,$srv_port,$errno,$errstr,$timeout); if (!$fp){ echo('fp fail'); } $content_length = strlen($post_str); $post_header = "POST $url HTTP/1.1\r\n"; $post_header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $post_header .= "User-Agent: MSIE\r\n"; $post_header .= "Host: ".$srv_ip."\r\n"; $post_header .= "Content-Length: ".$content_length."\r\n"; $post_header .= "Connection: close\r\n\r\n"; $post_header .= $post_str."\r\n\r\n"; fwrite($fp,$post_header); $inheader = 1; while(!feof($fp)){//測試文件指針是否到了文件結束的位置 
   $line = fgets($fp,1024); //去掉請求包的頭信息 
   if ($inheader && ($line == "\n" || $line == "\r\n")) { $inheader = 0; } if ($inheader == 0) { echo $line; } } fclose($fp); unset ($line); ?> 

其它博文

https://blog.csdn.net/navioo/article/details/82771663


免責聲明!

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



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