У меня есть команда в моем приложении Symfony, запущенном Cron. Я хочу иметь возможность ограничить количество экземпляров, выполняемых одновременно на моем сервере, скажем, 4 экземпляра. Я понятия не имею, как это сделать. Я нашел, как заблокировать команду, чтобы запустить команду только один раз и дождаться ее завершения, но я не знаю, как запустить более одного и все равно ограничить количество экземпляров. У вас есть идея?
Ограничить количество экземпляров Symfony Command
Ответы (4)
То, что вы ищете, это semaphore
.
В настоящее время запланировано LockComponent
для версии 3.4 (было взято из версии 3.3). Это значительное улучшение по сравнению с LockHandler
в FilesystemComponent
.
В крайнем случае вы, вероятно, можете объединить фиксированное количество блокировок из LockHandler
. Я не рекомендую его, потому что он использует flock
в файловой системе. Это ограничивает блокировку одним сервером. Кроме того, в некоторых системах flock
может быть ограничен областью процесса.
<?php
use Symfony\Component\Filesystem\LockHandler;
define('LOCK_ID', 'some-identifier');
define('LOCK_MAX', 5);
$lockPool = [];
for ($i = 0; $i <= LOCK_MAX;) {
$lockHandle = sprintf('%s-%s.lock', LOCK_ID, ++$i);
$lockPool[$i] = new LockHandler($lockHandle);
}
$activeLock = null;
$lockTimeout = 60 * 1000;
$lockWaitStart = microtime(true);
while(!$activeLock) {
foreach ($lockPool as $lockHandler) {
if ($lockHandler->lock()) {
$activeLock = $lockHandler;
break 2;
}
}
if ($lockTimeout && ($lockTimeout > microtime(true) - $lockWaitStart)) {
break;
}
// Randomly wait between 0.1ms and 10ms
usleep(mt_rand(100, 10000));
}
Гораздо лучшим и эффективным решением было бы использовать расширение семафора и немного поколдовать с ftok
, shm_*
и sem_*
.
я предлагаю вам использовать систему управления технологическим процессом в качестве руководителя. он довольно прост в использовании, и вы можете выбрать, сколько экземпляров вашего скрипта вы запускаете.
Вы можете использовать общий файл счетчика, который содержит счетчик, который увеличивается, когда команда начинает выполняться, и уменьшается до ее завершения.
Другим решением будет проверка списка процессов примерно так:
$processCount = exec('ps aux | grep "some part of the console command you run" | grep -v "grep" | wc -l' );
if(!empty($processCount) && $processCount >= X) {
return false;
}
Вы можете создать «команду запуска», выполняемую вашим cron или руководителем.
Эта команда Symfony может запускать ваши экземпляры с компонентом процесса на вашем сервере. Вы также можете проверить все, что хотите, и сделать все, что хотите, как функция exec
php.