그룹의 요청에 따라 서비스 계정에 대한 플래시 세일 기능을 만들었습니다. 플래시 세일을 테스트해야 해서 PHP 멀티스레딩을 시도해보고 싶어서 주문 잡기 기능을 시뮬레이션했습니다. 이 기사는 주로 플래시 판매 및 주문 잡기 기능을 구현하기 위한 PHP 다중 스레드 시뮬레이션을 공유합니다. 관심 있는 친구들이 이를 참조하여 모든 사람에게 도움이 되기를 바랍니다.
먼저 플래시 세일 모듈의 아이디어에 대해 이야기해 보겠습니다.
일반적인 상황에서 사용자 플래시 세일 작업
1. 플래시 세일 요청 시작
2. 플래시 세일 대기열에 들어갑니다
3. 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 = [ 'goods_id' => 1, 'activity_id' => 1, 'user_id' => isset($this->params['user_id']) ? $this->params['user_id'] : $this->getCurrentThreadId(), ]; $startTime = microtime(true); $this->data = [ 'id' => $params['user_id'], 'result' => model_http_curl_get( $url, $params ), 'time' => microtime(true)-$startTime, 'now' => microtime(true), ]; } } } /** * 执行多线程 */ function model_thread_result_get($urls_array) { foreach ($urls_array as $key => $value) { $threadPool[$key] = new Threadrun($value["url"],['user_id'=>$value['user_id']]); $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 : 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2)'; $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 '<pre class="brush:php;toolbar:false">'; var_dump($val); echo ''; } /** * 写日志 * @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와 redis는 쇼핑몰 플래시 세일 기능 코드 공유를 실현합니다.
JS 스크립트는 웹 페이지 자동 플래시 세일 예시 공유를 실현합니다.
PHP 전자 상거래 웹 사이트 제품에 대한 권장 비디오 리소스 플래시 세일 기능
위 내용은 PHP는 플래시 세일 코드를 구현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!