У меня есть PHP-скрипт , который принимает N документов из MongoDB, разветвляет процесс на K дочерних процессов PHP, каждый процесс выполняет некоторые действия с каждым документом и пытается обновить информацию документа (см. Код ниже) .
В моем локальном окружении (Docker
) все круто, но на сервере (нет Docker
) иногда во время цикла происходят странные вещи ...
Случайным образом все разветвленные процессы не могут подключиться к MongoDB. Команда updateOne возвращает ошибку:
«Не удалось отправить команду« обновить »с базой данных« имя базы данных »: неверный ответ с сервера. В /vendor/mongodb/mongodb/src/Operation/Update.php по строке 158». * 1014 » *
Это происходит со всеми процессами одновременно только для одной (или нескольких) случайных итераций цикла. Когда каждый процесс переходит на другую итерацию (принимает следующий документ) - все снова в порядке. Я делаю 5 попыток написать в MongoDB.
Каждая попытка с задержкой +1 секунда от предыдущей, поэтому первая попытка выполняется немедленно, если обнаруживается какое-либо исключение - подождите секунду и повторите попытку, следующая попытка будет через 2 секунды и так далее. Но это не помогает, все эти 5 попыток сломаны.
Это не проблема mongoDB, журнал пуст и даже не получает ничего от PHP, когда происходит ошибка.
Также я признаю, что чем больше одновременных процессов я запускаю, тем чаще встречаются ошибки.
Также это не проблема с ресурсом сервера, когда возникает ошибка, половина оперативной памяти (4 гигабайта) свободна, а процессор работает на половину своей мощности.
Может быть, PHP имеет некоторую конфигурацию для этого? Некоторые ограничения памяти или что-то ...
Я использую PHP v 7.1.30
MongoDB v 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);
}
}