python秒杀商品 多线程_PHP多线程模拟实现秒杀抢单

应集团要求给服务号做了个抢单秒杀的功能,需要对秒杀做个测试,想试试PHP多线程,就模拟了下抢单功能。

先说秒杀模块的思路:

正常情况下的用户秒杀操作

1、发起秒杀请求

2、进入秒杀队列

3、随机滞后 1 - 2 秒进行秒杀结果查询请求(算是变相分流吧)

4、成功则生成订单

5、返回结果

以下是模拟秒杀的代码:

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 '

';

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 出马。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值