linux popen阻塞_popen如何实现多进程并发执行,循环里的pclose会等待进程完毕再进行下一次循环...

通过RabbitMQ的prefetch机制和Redis队列,可以实现popen多进程并发执行,避免阻塞。在PHP中,当Redis队列长度小于预设值时,启动新的进程执行任务,并利用pcntl_fork和pcntl_wait配合,确保每个进程独立处理任务。
摘要由CSDN通过智能技术生成

谢邀.

如果你们有RabbitMQ的构架和经验, 实现这个很方便

rabbitmq 消息的消费端 channel 可以设置 prefetch=5, 即最多同时处理5条消息

rabbitmq 还有完善的ack机制, 即消息回执(该消息已正确处理完毕, 给我下条消息吧)

而且, 不会堵塞你当前PHP的进程, 后台(消费worker)会以5个并发的情形, 慢慢处理完这些任务

简单的可从Redis的List入手, 堵塞时判断队列的长度, 小于5时才开始popen并追加到队列

test.php

$redis = new \Redis();

$redis->connect("127.0.0.1", 6379);

$queue_name = "myqueue";

$queue_prefetch = 5;

$redis->delete($queue_name); // delete fro reseting.

for($i=0; $i<17; $i++){

while(1){

$count = count($redis->lRange($queue_name, 0, -1));

if($count <= $queue_prefetch) break;

usleep(20); // 堵塞20ms, 视情况而定, 太低redis I/O 会比较频繁

}

$redis->rPush($queue_name, $i);

$pid = pcntl_fork(); // 开启子进程, 需要pcntl模块

if($pid){

pclose(popen("/usr/bin/php /diandao/script.php $i $pid $queue_name", "w"));

pcntl_wait($status);

}

}

/diandao/script.php

sleep(1); // 模拟处理超过1秒

$index = $argv[1];

$pid = $argv[2];

$queue = $argv[3];

$redis = new Redis;

$redis->connect("127.0.0.1", 6379);

$f = fopen("/diandao/script.log", "a+");

$date = date("Y-m-d H:i:s");

fwrite($f, "[$date] ".json_encode($argv).PHP_EOL );

fclose($f);

$redis->lRem($queue, $index);

/diandao/script.log 结果

数量判断那多写了个=号, 所以并发变成了6个

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值