前提:在网上到出找资料都是需要安装多线程扩展,还有自己调用自己的接口CUrl请求自己1秒终端等,感觉麻烦本人比较懒,不想找运维安装扩展调试加班搞,在思考大半天后想起Laravel可以并发执行命定时脚本也能传参数,说干就干,首先咱们需要配置好Crontab脚本,本文方法是利用Linux的crontab定时任务来协助实现Laravel调度(Mac也一样)。
咱们在部署之前最好在shell跑一下:
我的会报错要去php.ini文件去除禁用函数
一切可用之后用命令crontab -e 添加如下内容:
* * * * * /usr/local/bin/php /usr/local/var/www/projectName/artisan schedule:run >> /dev/null 2>&1
服务器的准备好之后开始代码:
咱们先在app/Console/Kernel.php文件 schedule方法内:
for ($i = 1; $i <= 10;$i++ ){
$schedule->command("command:getInventoryByASN --num=$i")->everyMinute()->runInBackground();//商品授权每五分钟跑一次
}
10代表开的进程数,你可以安装自己的实际配置来选择。 $i 为传入线程识别号用它来做分批处理;runInBackground() 后台执行代表多条命令并发运行,命令必须在linux环境跑,windows在会报错要去运行。
注意要加文件锁一个进程对应一个锁,否则会出现重复处理的问题,我用的Laravel5.4版本withoutOverlapping()方法实测不管用。
<?php
namespace App\Console\Commands;
use App\CustomerInfo;
use App\GcReceiving;
use App\Lib\Helps\Common;
use App\LogHelper;
use Illuminate\Console\Command;
class getInventoryByASN extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'command:getInventoryByASN {--num=}';
/**
* @var string 多进程任务文件锁名称
*/
private $fileLock = 'getInventoryByASN';
/**
* The console command description.
*
* @var string
*/
protected $description = '根据入库单获取库存';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
//执行前
public function before($num = 1)
{
$dir = storage_path();
$flagFile = $dir . DIRECTORY_SEPARATOR . $this->fileLock . $num. '.lock';
if (file_exists($flagFile)) {
//如果锁文件存在时间过长删除锁文件
if (time() - filemtime($flagFile) > 7200) {
@unlink($flagFile);
}
}
//如果锁文件存在,程序已经运行.
if (file_exists($flagFile)) {
echo "Is already running,please unlock! \n";
exit(0);
}
//加锁,创建锁文件
touch($flagFile);
if (preg_match('/linux/i', PHP_OS) || preg_match('/Unix/i', PHP_OS)) {
chmod($flagFile, 0777);
}
}
public function end($num = 1)
{
$dir = storage_path();
$flagFile = $dir . DIRECTORY_SEPARATOR . $this->fileLock . $num. '.lock';
//解锁,删除锁文件
unlink($flagFile);
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$num = $this->option('num') ?? 1;
try {
$this->before($num);
ignore_user_abort(true);
set_time_limit (0);
date_default_timezone_set('PRC');//设置时间为中国时区
ini_set('memory_limit', '1024M');
// exec("chcp 65001");//设置命令行窗口为中文编码
$logInfo = [
'task_time'=>'任务时间:'.date('Y-m-d H:i:s',time()),
'task_name'=>'批次入库单商品库存信息同步定时任务',
'remark'=>'任务开始',
];
$start = date('Y-m-d H:i:s');
//codeing
LogHelper::setExceptionLog($logInfo,'inventory_asn');
GcReceiving::getPendingReceiveinfoChunk ($num);
$mem = round(memory_get_peak_usage() / 1024 / 1024, 2);
file_put_contents('task.log',"进程:".$num."----- 开始时间: $start------- 结束时间:". date('Y-m-d H:i:s')." ----- 同步完成;内存峰值: $mem MB;"."\n", FILE_APPEND);
} catch (\Exception $e) {
} finally{
$logInfo = [
'task_time'=>'任务时间:'.date('Y-m-d H:i:s',time()),
'task_name'=>'批次入库单商品库存信息同步定时任务',
'remark'=>'任务结束',
];
LogHelper::setExceptionLog($logInfo,'inventory_asn');
$this->end($num);
}
}
}
在shell产生10个进程在运行,多进程运行代码成功: