Когда новый пользователь регистрируется на моем сайте, я хочу сделать предварительную обработку, чтобы сократить их поиски в будущем. Это связано с временем обработки от 30 до 2 минут. Очевидно, я не могу этого сделать, когда они нажимают кнопку отправки при регистрации … или на любой странице PHP, которую они посещают. Тем не менее, я хотел бы, чтобы это было сделано в течение 5 минут после их регистрации (или меньше).
Cron Route Я думаю, что это должно быть в задании cron, и если да, то как мне настроить работу cron? Если да, то как должна выглядеть моя линия cron каждые 2 минуты, и как я могу застраховать, чтобы у меня не было того же задания cron, которое перекрывало следующее?
Event / Fork Route – Preferred. Если я могу выбросить какое-то событие на свой сервер, не нарушая работу моих пользователей или не разблокируя процесс регистрации пользователей (вместо задания cron), как я могу это сделать?
Я бы не рекомендовал ни одного решения.
Вместо этого вам будет лучше работать с длинным запуском процесса (daemon), который получает свои задания из очереди сообщений . Сама очередь сообщений может быть отключена от базы данных, если это ваш предпочтительный метод.
Вы отправите идентификатор задания в свою базу данных, а затем продолжительный процесс будет периодически проходить через них и действовать на них.
Это так просто:
<?php while(true) { jobs = getListOfJobsFromDatabase(); // get the jobs from the databbase foreach (jobs as job) { processAJob(job); // do whatever needs to be done for the job deleteJobFromDatabase(job); //remember to delete the job once its done! } sleep(60); // sleep for a while so it doesnt thrash your database when theres nothing to do } ?>
И просто запустите этот скрипт из командной строки.
Преимущество этого в работе cron заключается в том, что вы не получите условия гонки.
Вы также можете отказаться от фактической обработки заданий, поэтому многие из них могут выполняться параллельно, а не обрабатываться последовательно.
Вы можете использовать следующий класс для вызова фоновой задачи PHP.
class BackgroundProcess { static function open($exec, $cwd = null) { if (!is_string($cwd)) { $cwd = @getcwd(); } @chdir($cwd); if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { $WshShell = new COM("WScript.Shell"); $WshShell->CurrentDirectory = str_replace('/', '\\', $cwd); $WshShell->Run($exec, 0, false); } else { exec($exec . " > /dev/null 2>&1 &"); } } static function fork($phpScript, $phpExec = null) { $cwd = dirname($phpScript); if (!is_string($phpExec) || !file_exists($phpExec)) { if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { $phpExec = str_replace('/', '\\', dirname(ini_get('extension_dir'))) . '\php.exe'; if (@file_exists($phpExec)) { BackgroundProcess::open(escapeshellarg($phpExec) . " " . escapeshellarg($phpScript), $cwd); } } else { $phpExec = exec("which php-cli"); if ($phpExec[0] != '/') { $phpExec = exec("which php"); } if ($phpExec[0] == '/') { BackgroundProcess::open(escapeshellarg($phpExec) . " " . escapeshellarg($phpScript), $cwd); } } } else { if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { $phpExec = str_replace('/', '\\', $phpExec); } BackgroundProcess::open(escapeshellarg($phpExec) . " " . escapeshellarg($phpScript), $cwd); } } }
Использовать как таковой:
BackgroundProcess::fork('process_user.php');
Вот что я думаю. У вас есть один cron для всех ваших пользователей. Таким образом, вы можете не накладывать друг на друга, помещая их в таблицу, которая работает как очередь. Запускайте cron каждый час, но сначала проверяйте очередь, если очередь не пуста. Если он не пропустит задание cron в течение часа, попробуйте снова следующее.