>  기사  >  백엔드 개발  >  플래시 판매 및 주문 확보를 위한 PHP 멀티 스레드 시뮬레이션

플래시 판매 및 주문 확보를 위한 PHP 멀티 스레드 시뮬레이션

不言
不言원래의
2018-05-05 09:46:482006검색

이 글에서는 플래시 판매 및 주문 잡기 기능을 구체적으로 구현하기 위한 PHP 멀티 스레드 시뮬레이션을 주로 소개합니다. 관심 있는 친구들이 참고할 수 있습니다.

그룹의 요청에 따라 플래시를 만들었습니다. 서비스 계정에 대한 판매 기능, 플래시 판매를 테스트해야 하므로 PHP 멀티스레딩을 시도하고 싶어서 주문 잡기 기능을 시뮬레이션했습니다.

플래시 세일 모듈의 아이디어에 대해 먼저 이야기해 보겠습니다.

일반적인 상황에서 사용자 플래시 세일 작업

1. 플래시 세일 요청 시작
2. 플래시 세일을 시작합니다. 1~2초의 무작위 지연이 있는 결과 쿼리 요청(위장된 전환 바)
4. 성공하면 주문이 생성됩니다.
5. 결과 반환

다음은 플래시 세일을 시뮬레이션하는 코드입니다.

<?php


set_time_limit(0);

/**
* 线程的执行任务
*/
class Threadrun extends Thread
{
  public $url;
  public $data;
  public $params;

  public function __construct($url, $params=[])
  {
   $this->url = $url;
   $this->params = $params;
  }

  public function run()
  {
   if(($url = $this->url))
   {
     $params = [
      &#39;goods_id&#39;  => 1,
      &#39;activity_id&#39;  => 1,
      &#39;user_id&#39;   => isset($this->params[&#39;user_id&#39;]) ? $this->params[&#39;user_id&#39;] : $this->getCurrentThreadId(),
     ];
     $startTime = microtime(true);
     $this->data = [
      &#39;id&#39;   => $params[&#39;user_id&#39;],
      &#39;result&#39;  => model_http_curl_get( $url, $params ),
      &#39;time&#39;  => microtime(true)-$startTime,
      &#39;now&#39;   => microtime(true),
     ];
   }
  }
}

/**
* 执行多线程
*/
function model_thread_result_get($urls_array)
{
  foreach ($urls_array as $key => $value)
  {
   $threadPool[$key] = new Threadrun($value["url"],[&#39;user_id&#39;=>$value[&#39;user_id&#39;]]);
   $threadPool[$key]->start();
  }
  foreach ($threadPool as $thread_key => $thread_value)
  {
   while($threadPool[$thread_key]->isRunning())
   {
     usleep(10);
   }
   if($threadPool[$thread_key]->join())
   {
     $variable_data[$thread_key] = $threadPool[$thread_key]->data;
   }
  }
  return $variable_data;
}

/**
* 发送 HTTP 请求
*/
function model_http_curl_get($url,$data=[],$userAgent="")
{
  $userAgent = $userAgent ? $userAgent : &#39;Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2)&#39;;
  $curl = curl_init();
  curl_setopt($curl, CURLOPT_URL, $url);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($curl, CURLOPT_TIMEOUT, 5);
  curl_setopt($curl, CURLOPT_USERAGENT, $userAgent);
  curl_setopt($curl, CURLOPT_POST, true);
  if( !empty($data) ) {
   curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
  }
  $result = curl_exec($curl);
  curl_close($curl);
  return $result;
}


/**
 * 友好的打印变量
 * @param $val
 */
function dump( $val )
{
  echo &#39;<pre class="brush:php;toolbar:false">&#39;;
  var_dump($val);
  echo &#39;
'; } /** * 写日志 * @param $msg * @param string $logPath */ function writeLog( $msg, $logPath='' ) { if( empty($logPath) ) { $logPath = date('Y_m_d').'.log'; } if( !file_exists($logPath) ) { $fp = fopen( $logPath,'w' ); fclose( $fp ); } error_log( $msg.PHP_EOL, 3, $logPath); } /** * 生成日志信息 * @param $result * @param $timeDiff * @return bool|string */ function createLog( $result, $timeDiff ){ if( empty($result) || !is_array($result) ) { return false; } $succeed = 0; $fail = 0; foreach( $result as $v ) { $times[] = $v['time']; $v['result'] === false ? $fail++ : $succeed++; } $totalTime = array_sum( $times ); $maxTime = max( $times ); $minTime = min( $times ); $sum = count( $times ); $avgTime = $totalTime/$sum; $segment = str_repeat('=',100); $flag = $segment . PHP_EOL; $flag .= '总共执行时间:' . $timeDiff . PHP_EOL ; $flag .= '最大执行时间:' . $maxTime . PHP_EOL; $flag .= '最小执行时间:' . $minTime . PHP_EOL; $flag .= '平均请求时间:' . $avgTime . PHP_EOL; $flag .= '请求数:' . $sum . PHP_EOL; $flag .= '请求成功数:' . $succeed . PHP_EOL; $flag .= '请求失败数:' . $fail . PHP_EOL; $flag .= $segment . PHP_EOL; return $flag; } /** * 发起秒杀请求 */ function insertList( $urls, $logPath='' ) { $t = microtime(true); $result = model_thread_result_get($urls); $e = microtime(true); $timeDiff = $e-$t; echo "总执行时间:" . $timeDiff . PHP_EOL; foreach( $result as $v ) { $msg = '用户【' . $v['id'] . '】秒杀商品, 返回结果 ' . $v['result'] . ' 用时【' . $v['time'] . ' 秒】 当前时间【'.$v['now'].'】'; writeLog( $msg,$logPath ); } $logStr = createLog( $result, $timeDiff); writeLog( $logStr, $logPath ); return $result; } //发起秒杀请求 for ($i=0; $i < 1000; $i++) { $urls_array[] = array("name" => "baidu", "url" => "http://***.***.com/seckill/shopping/listinsert"); } $list = insertList( $urls_array, './inset.log' ); //发起秒杀结果查询请求 $urls_array = []; foreach( $list as $v ) { if( $v['result'] === false ) { continue; } $urls_array[] = array( "name" => "baidu", "url" => "http://***.***.com/seckill/shopping/query", 'user_id' => $v['id'], ); } insertList( $urls_array, './query.log' );

테스트 코드 기계 성능(개발 기계):

주문 코드 기계 성능(테스트 기계):

시스템 테스트 결과:

1000개의 동시 상황을 시뮬레이션하면 단일 기계가 초당 300개 이상의 주문을 처리하며 서버에 부담이 없습니다.

반대로 테스트 머신이 이를 견디지 ​​못하고 CPU가 100% 급등했습니다. Apache가 때때로 충돌합니다.

PHP 멀티스레딩과 Windows 환경의 지원이 부족한 것인지, 아니면 PHP 멀티스레딩 자체의 문제인지는 모르겠지만 1000개의 스레드만 실행이 되지 않습니다. 멀티스레딩에는 여전히 Python과 C가 필요합니다.

관련 권장 사항:

PHP 멀티 스레드 시뮬레이션 구현의 세 가지 방법 소개

위 내용은 플래시 판매 및 주문 확보를 위한 PHP 멀티 스레드 시뮬레이션의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.