国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > PHP > 正文

PHP多線程模擬實(shí)現(xiàn)秒殺搶單

2024-05-04 21:50:18
字體:
供稿:網(wǎng)友

應(yīng)集團(tuán)要求給服務(wù)號(hào)做了個(gè)搶單秒殺的功能,需要對(duì)秒殺做個(gè)測(cè)試,想試試PHP多線程,就模擬了下?lián)寙喂δ堋?/p>

先說秒殺模塊的思路:

正常情況下的用戶秒殺操作

1、發(fā)起秒殺請(qǐng)求

2、進(jìn)入秒殺隊(duì)列

3、隨機(jī)滯后 1 - 2 秒進(jìn)行秒殺結(jié)果查詢請(qǐng)求(算是變相分流吧)

4、成功則生成訂單

5、返回結(jié)果

以下是模擬秒殺的代碼:

  1. <?php 
  2.   
  3.   
  4. set_time_limit(0); 
  5.   
  6. /** 
  7. * 線程的執(zhí)行任務(wù) 
  8. */ 
  9. class Threadrun extends Thread 
  10.   public $url
  11.   public $data
  12.   public $params
  13.   
  14.   public function __construct($url$params=[]) 
  15.   { 
  16.    $this->url = $url
  17.    $this->params = $params
  18.   } 
  19.   
  20.   public function run() 
  21.   { 
  22.    if(($url = $this->url)) 
  23.    { 
  24.      $params = [ 
  25.       'goods_id'  => 1, 
  26.       'activity_id'  => 1, 
  27.       'user_id'   => isset($this->params['user_id']) ? $this->params['user_id'] : $this->getCurrentThreadId(), 
  28.      ]; 
  29.      $startTime = microtime(true); 
  30.      $this->data = [ 
  31.       'id'   => $params['user_id'], 
  32.       'result'  => model_http_curl_get( $url$params ), 
  33.       'time'  => microtime(true)-$startTime
  34.       'now'   => microtime(true), 
  35.      ]; 
  36.    } 
  37.   } 
  38.   
  39. /** 
  40. * 執(zhí)行多線程 
  41. */ 
  42. function model_thread_result_get($urls_array
  43.   foreach ($urls_array as $key => $value
  44.   { 
  45.    $threadPool[$key] = new Threadrun($value["url"],['user_id'=>$value['user_id']]); 
  46.    $threadPool[$key]->start(); 
  47.   } 
  48.   foreach ($threadPool as $thread_key => $thread_value
  49.   { 
  50.    while($threadPool[$thread_key]->isRunning()) 
  51.    { 
  52.      usleep(10); 
  53.    } 
  54.    if($threadPool[$thread_key]->join()) 
  55.    { 
  56.      $variable_data[$thread_key] = $threadPool[$thread_key]->data; 
  57.    } 
  58.   } 
  59.   return $variable_data
  60.   
  61. /** 
  62. * 發(fā)送 HTTP 請(qǐng)求 
  63. */ 
  64. function model_http_curl_get($url,$data=[],$userAgent=""
  65.   $userAgent = $userAgent ? $userAgent : 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2)'
  66.   $curl = curl_init(); 
  67.   curl_setopt($curl, CURLOPT_URL, $url); 
  68.   curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 
  69.   curl_setopt($curl, CURLOPT_TIMEOUT, 5); 
  70.   curl_setopt($curl, CURLOPT_USERAGENT, $userAgent); 
  71.   curl_setopt($curl, CURLOPT_POST, true); 
  72.   if( !emptyempty($data) ) { 
  73.    curl_setopt($curl, CURLOPT_POSTFIELDS, $data); 
  74.   } 
  75.   $result = curl_exec($curl); 
  76.   curl_close($curl); 
  77.   return $result
  78.   
  79.   
  80. /** 
  81.  * 友好的打印變量 
  82.  * @param $val 
  83.  */ 
  84. function dump( $val ) 
  85.   echo '<pre>'
  86.   var_dump($val); 
  87.   echo '</pre>'
  88.   
  89. /** 
  90.  * 寫日志 
  91.  * @param $msg 
  92.  * @param string $logPath 
  93.  */ 
  94. function writeLog( $msg$logPath='' ) { 
  95.   ifemptyempty($logPath) ) { 
  96.    $logPath = date('Y_m_d').'.log'
  97.   } 
  98.   if( !file_exists($logPath) ) { 
  99.    $fp = fopen$logPath,'w' ); 
  100.    fclose( $fp ); 
  101.   } 
  102.   error_log$msg.PHP_EOL, 3, $logPath); 
  103.   
  104. /** 
  105.  * 生成日志信息 
  106.  * @param $result 
  107.  * @param $timeDiff 
  108.  * @return bool|string 
  109.  */ 
  110. function createLog( $result$timeDiff ){ 
  111.   ifemptyempty($result) || !is_array($result) ) { 
  112.    return false; 
  113.   } 
  114.   $succeed = 0; 
  115.   $fail = 0; 
  116.   foreach$result as $v ) { 
  117.    $times[] = $v['time']; 
  118.    $v['result'] === false ? $fail++ : $succeed++; 
  119.   } 
  120.   $totalTime = array_sum$times ); 
  121.   $maxTime = max( $times ); 
  122.   $minTime = min( $times ); 
  123.   $sum = count$times ); 
  124.   $avgTime = $totalTime/$sum
  125.   $segment = str_repeat('=',100); 
  126.   $flag = $segment . PHP_EOL; 
  127.   $flag .= '總共執(zhí)行時(shí)間:' . $timeDiff . PHP_EOL ; 
  128.   $flag .= '最大執(zhí)行時(shí)間:' . $maxTime . PHP_EOL; 
  129.   $flag .= '最小執(zhí)行時(shí)間:' . $minTime . PHP_EOL; 
  130.   $flag .= '平均請(qǐng)求時(shí)間:' . $avgTime . PHP_EOL; 
  131.   $flag .= '請(qǐng)求數(shù):' . $sum . PHP_EOL; 
  132.   $flag .= '請(qǐng)求成功數(shù):' . $succeed . PHP_EOL; 
  133.   $flag .= '請(qǐng)求失敗數(shù):' . $fail . PHP_EOL; 
  134.   $flag .= $segment . PHP_EOL; 
  135.   return $flag
  136.   
  137.   
  138.   
  139. /** 
  140.  * 發(fā)起秒殺請(qǐng)求 
  141.  */ 
  142. function insertList( $urls$logPath='' ) 
  143.   $t = microtime(true); 
  144.   $result = model_thread_result_get($urls); 
  145.   $e = microtime(true); 
  146.   $timeDiff = $e-$t
  147.   echo "總執(zhí)行時(shí)間:" . $timeDiff . PHP_EOL; 
  148.   foreach$result as $v ) { 
  149.    $msg = '用戶【' . $v['id'] . '】秒殺商品, 返回結(jié)果 ' . $v['result'] . ' 用時(shí)【' . $v['time'] . ' 秒】 當(dāng)前時(shí)間【'.$v['now'].'】'
  150.    writeLog( $msg,$logPath ); 
  151.   } 
  152.   $logStr = createLog( $result$timeDiff); 
  153.   writeLog( $logStr$logPath ); 
  154.   return $result
  155.   
  156.   
  157. //發(fā)起秒殺請(qǐng)求 
  158. for ($i=0; $i < 1000; $i++) 
  159.   $urls_array[] = array("name" => "baidu""url" => "http://***.***.com/seckill/shopping/listinsert"); 
  160.   
  161. $list = insertList( $urls_array'./inset.log' ); 
  162.   
  163. //發(fā)起秒殺結(jié)果查詢請(qǐng)求 
  164. $urls_array = []; 
  165. foreach$list as $v ) { 
  166.   if$v['result'] === false ) { 
  167.    continue
  168.   } 
  169.   $urls_array[] = array
  170.         "name"  => "baidu"
  171.         "url"  => "http://***.***.com/seckill/shopping/query"
  172.         'user_id' => $v['id'], 
  173.   );//Vevb.com 
  174. insertList( $urls_array'./query.log' ); 

系統(tǒng)測(cè)試結(jié)果:

模擬 1000 并發(fā)的情況,單機(jī)每秒 300+ 訂單,服務(wù)器毫無壓力。

反倒是測(cè)試機(jī)受不了了,CPU 飆升 100%。 Apache 偶爾崩潰。

不知道是 PHP 多線程和 Windows 環(huán)境的支持不好,還是 PHP 多線程本身的問題,區(qū)區(qū) 1000 線程跑不動(dòng)。多線程的地方還是比較需要 Python 和 C 出馬。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 四川省| 大邑县| 甘孜县| 德州市| 井冈山市| 武隆县| 电白县| 张掖市| 津南区| 株洲市| 精河县| 广元市| 凤山市| 同江市| 石城县| 奉化市| 清流县| 平果县| 大埔区| 隆德县| 湄潭县| 潮州市| 南岸区| 遵化市| 遂昌县| 手游| 宝山区| 纳雍县| 攀枝花市| 上饶市| 德庆县| 启东市| 司法| 广南县| 桑植县| 盐源县| 赤水市| 弥渡县| 百色市| 东光县| 威信县|