php多线程问题
我正在编写一个php cron作业,它使用curl读取数千个提要/网页,并将内容存储在数据库中。如何将线程数限制为6个?i、 例如,尽管我需要扫描数千个提要/网页,但我希望在任何时候只有6个curl线程处于活动状态,这样我的服务器和网络就不会陷入困境。我可以在Java中使用wait、notify、notify对象的所有方法轻松地完成这项工作。我应该构建自己的信号量还是php提供任何内置函数?首先,php没有线程,但它有进程控制: 我围绕这些函数构建了一个类,以帮助满足我的多进程需求 我也有类似的情况。我保存了从cron开始的进程及其状态的日志。我正在从一个相关的cron工作中检查它们 编辑(更多详细信息): 在我的项目中,我记录对数据库的所有关键更改。如果变更符合行动标准,则可采取行动。所以我现在做的和你不一样。然而,也有一些相似之处 当我派生一个新进程时,我在DB表中输入它的pid。然后,下次cron作业启动时,它所做的部分工作是检查进程是否正确完成,然后在该DB表中将操作标记为已完成 你没有给出很多关于你的项目的细节。所以我只想提出一个建议:php多线程问题,php,multithreading,curl,semaphore,Php,Multithreading,Curl,Semaphore,我正在编写一个php cron作业,它使用curl读取数千个提要/网页,并将内容存储在数据库中。如何将线程数限制为6个?i、 例如,尽管我需要扫描数千个提要/网页,但我希望在任何时候只有6个curl线程处于活动状态,这样我的服务器和网络就不会陷入困境。我可以在Java中使用wait、notify、notify对象的所有方法轻松地完成这项工作。我应该构建自己的信号量还是php提供任何内置函数?首先,php没有线程,但它有进程控制: 我围绕这些函数构建了一个类,以帮助满足我的多进程需求 我也有类似
- DB表包含要下载的资源的URL
- 另一个表保存运行进程的PID
- 每小时运行一次的cron作业将遍历表并下载资源并将其存储在数据库中。但是,它首先检查pid表中是否有完整/失效/正在运行的进程,并采取相应的行动。在这里,您可以将进程限制为6个
我对proc_close(10到30秒)有问题,所以我只是使用linux命令kill终止了进程
Curl有时会在不同的服务器(ubuntu、centos)上为我冻结,但不是在所有服务器上,所以我会杀死任何超过40秒的“子”进程,因为通常脚本最多需要10秒,我宁愿重做,也不愿等待一分钟左右Curl解除冻结
$options=array();
$option['sleep-after-destroy']=0;
$option['sleep-after-create']=0;
$option['age-max']=40;
$option['dir-run']=dirname(__FILE__);
$option['step-sleep']=1;
$option['workers-max']=6;
$option['destroy-forcefull']=1;
$workers=array();
function endAWorker($i,$cansleep=true) {
global $workers;
global $option;
global $child_time_limit;
if(isset($workers[$i])) {
@doE('Ending worker [['.$i.']]'."\n");
if($option['destroy-forcefull']==1) {
$x=exec('ps x | grep "php check_working_child.php '.$i.' '.$child_time_limit.'" | grep -v "grep" | grep -v "sh -c"');
echo 'pscomm> '.$x."\n";
$x=explode(' ',trim(str_replace("\t",' ',$x)));
//print_r($x);
if(is_numeric($x[0])) {
$c='kill -9 '.$x[0];
echo 'killcommand> '.$c."\n";
$x=exec($c);
}
}
@proc_close($workers[$i]['link']);
unset($workers[$i]);
}
if($cansleep==true) {
sleep($option['sleep-after-destroy']);
}
}
function startAWorker($i) {
global $workers;
global $option;
global $child_time_limit;
$runcommand='php check_working_child.php '.$i.' '.$child_time_limit.' > check_working_child_logs/'.$i.'.normal.log';
doE('Starting [['.$i.']]: '.$runcommand."\n");
$workers[$i]=array(
'desc' => array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("file", 'check_working_child_logs/'.$i.'.error.log', "a")
),
'pipes' => null,
'link' => null,
'start-time' => mktime()
);
$workers[$i]['link']=proc_open(
$runcommand,
$workers[$i]['desc'],
$workers[$i]['pipes'],
$option['dir-run']
);
sleep($option['sleep-after-create']);
}
function checkAWorker($i) {
global $workers;
global $option;
$temp=proc_get_status($workers[$i]['link']);
if($temp['running']===false) {
doE('Worker [['.$i.']] finished'."\n");
if(is_file('check_working_child_logs/'.$i.'.normal.log') && filesize('check_working_child_logs/'.$i.'.normal.log')>0) {
doE('--------'."\n");
echo file_get_contents('check_working_child_logs/'.$i.'.normal.log');
doE('-------'."\n");
}
endAWorker($i);
} else {
if($option['age-max']>0) {
if($workers[$i]['start-time']+$option['age-max']$v) {
endAWorker($i,false);
}
@doE('Done killing workers.'."\n");
}
register_shutdown_function('endAllWorkers');
while(1) {
$step++;
foreach($workers as $index=>$v) {
checkAWorker($index);
}
if(count($workers)==$option['workers-max']) {
} elseif(count($workers)$option['workers-max']) {
$wl=array_keys($workers);
$wl=array_pop($wl);
doE('Killing worker [['.$wl.']]');
endAWorker($wl[0]);
}
}
并创建一个名为“check_working_child.php”的文件来完成所有工作,第一个参数是实例号,第二个参数是时间限制
php check\u working\u child.php 5 60
意味着你是第五个孩子,可以跑60秒
如果上面的代码没有运行,请告诉我,我将使用pastebin或其他工具发布它。PHP没有线程化。除非您使用的是curl_multi*函数族,否则您的curl请求将一直阻止,直到完成为止。我最终使用库来满足我的需要。没有进程,没有线程。谢谢你的快速回答。如何在6个进程之间同步计数器?两个进程不应该试图同时更新计数器。我已经在答案中添加了一些细节。我不知道你的项目是如何组织的,所以我不能确定这是否适合你,但我希望它能帮助你。