gpt4 book ai didi

php - fork PHP 进程中的连接错误

转载 作者:可可西里 更新时间:2023-11-01 10:45:02 25 4
gpt4 key购买 nike

我有一个 PHP 脚本,它从 MongoDB 获取 N 个文档,将进程 fork 为 K 个子 PHP 进程,每个进程对每个文档做一些事情并尝试更新文档的信息(见下面的代码).

在我的本地环境 (Docker) 上一切都很好,但是在服务器上(没有 Docker 那里)有时在循环期间会发生奇怪的事情......

随机所有 fork 进程无法连接到 MongoDB。 updateOne 命令返回错误:

"Failed to send "update" command with database "databasename": Invalid reply from server. in /vendor/mongodb/mongodb/src/Operation/Update.php on line 158".

这仅在一次(或多次)随机循环迭代中同时发生在所有进程中。当每个进程进入另一个迭代(获取下一个文档)时——一切又都正常了。我尝试了 5 次写入 MongoDB。

每次尝试都比上一次延迟+1秒,所以第一次尝试会立即执行,如果捕获到任何异常——稍等片刻再重试,下一次尝试将在2秒等等。但这无济于事,这 5 次尝试都失败了。

这不是 mongoDB 的问题,它的日志是空的,当发生错误时它甚至没有从 PHP 收到任何东西。

我也承认,我同时运行的进程越多——发生错误的频率就越高。

这也不是服务器资源问题,当发生错误时,一半的 RAM (4 gig) 是空闲的,CPU 正在使用它一半的功率。

也许 PHP 对此有一些配置?一些内存限制或其他...

我使用 PHP v 7.1.30MongoDB 3.2.16 版PHP 包 mongodb/mongodb v 1.1.2

<?php

$processesAmount = 5;
$documents = $this->mongoResource->getDocuments();

for ($processNumber = 0; $processNumber < $processesAmount; $processNumber++) {
// create child process
$pid = pcntl_fork();

// do not create new processes in child processes
if ($pid === 0) {
break;
}

if ($pid === -1) {
// some errors catching staff here...
}
else if ($pid === 0) {
// create new MongoDB connection
}
else {
// Protect against Zombie children
// main process waits before all child processes end
for ($i = 0; $i < $processesAmount; $i++) {
pcntl_wait($status);
}
return null;
}

// spread documents to each process without duplicates
for ($i = $processNumber; $i < count($documents); $i += $processesAmount) {
$newDocumentData = $this->doSomeStaffWithDocument($documents[$i]);
$this->mongoResource->updateDocument($documents[$i], $newDocumentData);
}
}

最佳答案

这里可能有很多问题,一个是所有进程都共享一个数据库连接,第一个连接然后断开连接并终止所有连接。在此处检查文档中的第二个示例:https://www.php.net/manual/en/ref.pcntl.php

如果这没有帮助,那么我阅读您的代码的方式就是“传播”部分在每个进程中都在发生,而它本应发生一次。您不应该像下面这样将“工作”放在子部分吗?

$processesAmount = 5;
$documents = $this->mongoResource->getDocuments();
$numDocs = count($documents);
$i = 0;
$children = [];

for ($processNumber = 0; $processNumber < $processesAmount; $processNumber++) {
// create child
$pid = pcntl_fork();

if ($pid === -1) {
// some errors catching staff here...
} else if ($pid) {
//parent
$children[] = $pid;
} else {
//child
while (!empty($documents) && $i <= $numDocs) {
$i += $processNumber;
$doc = $documents[$i] ?? null;
unset($documents[$i]);
$newDocumentData = $this->doSomeStaffWithDocument($doc);
$this->mongoResource->updateDocument($doc, $newDocumentData);
}
}
}

//protect against zombies and wait for parent
//children is always empty unless in parent
while (!empty($children)) {

foreach ($children as $key => $pid) {

$status = null;

$res = pcntl_waitpid($pid, $status, WNOHANG);

if ($res == -1 || $res > 0) { //if the process has already exited
unset($children[$key]);
}

}

}

}

关于php - fork PHP 进程中的连接错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56878185/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com