В настоящее время я работаю над внутренним веб-сайтом, на котором отображается много статистики, а некоторые страницы или сценарии ajax работают очень медленно из-за больших объемов данных.
Я ищу способ запустить эти сценарии в фоновом режиме с запросом, а затем запустить запросы ajax, чтобы узнать о ходе выполнения фонового сценария.
Есть ли способ добиться этого? Я работаю с php7.0 и сервером apache2 (у меня нет прямого доступа к конфигурации сервера apache, поэтому, если это возможно, я ищу вариант на стороне клиента)
У меня есть доступ к файлам на сервере, к модификациям crontab и к серверу MySQL. По поводу чего-нибудь еще я могу попросить мою поддержку в выполнении этой работы (но они не всегда очень готовы к сотрудничеству ...). Спрошу очередь / рабочих






вы можете создать скрипт php для выполнения скрипта оболочки bash или использовать для этого метод exec()
Да, но сценарий убивается, когда умирает сценарий php, не так ли?
много вещей, чтобы справиться с этим, вы можете использовать какую-либо службу для проверки процесса, например Monit, или вы даже можете заставить службу cron выполнить процесс снова
Если кто-то еще ищет способ добиться этого, вот решение, которое я нашел:
Я вызываю в Ajax скрипт, он разветвляется и сохраняет PID дочернего процесса в базе данных. Затем я вызываю session_write_close () в дочернем процессе, чтобы позволить пользователю делать новые запросы, и родительский процесс завершается (не дожидаясь завершения дочернего процесса). Когда отец уходит, пользователь получает ответ на свой запрос, и дочерний процесс продолжает свою работу.
Затем в Ajax я вызываю другой сценарий, чтобы получить эволюцию рабочего, и, наконец, я получаю результат и убиваю дочерний процесс, когда все будет сделано.
Вот код моего рабочего класса:
class AsyncWorker
{
private $pid;
private $worker;
private $wMgr;
public function __construct($action, $content, $params = NULL)
{
$this->wMgr = new WorkersManager();
$pid = pcntl_fork(); // Process Fork
if ($pid < 0) {
Ajax::Response(AJX_ERR, "Impossible de fork le processus");
} else if ($pid == 0) { // In the child, we start the job and save the worker properties
sleep(1);
$this->pid = getmypid();
$this->worker = $this->wMgr->fetchBy(array("pid" => $this->pid));
if (!$this->worker) {
$this->worker = $this->wMgr->getEmptyObject();
$this->wMgr->create($this->worker);
}
$this->worker->setPid($this->pid);
$this->worker->setAction($action);
$this->worker->setContent($content);
$this->worker->setPercent(0.00);
$this->worker->setResult("");
$this->wMgr->update($this->worker);
$this->launch($params);
} else { // In the father, we save the pid to DB and answer the request.
$this->worker = $this->wMgr->fetchBy(array("pid" => $this->pid));
if (!$this->worker) {
$this->worker = $this->wMgr->getEmptyObject();
$this->worker->setPid($pid);
$this->wMgr->create($this->worker);
}
Ajax::Response(AJX_OK, "Worker started", $this->worker->getId());
}
}
// Worker job
private function launch($params = NULL)
{
global $form, $_PHPPATH, $url, $session;
session_write_close(); // This is useful to let the user make new requests
ob_start(); // Avoid writing anything
/*
** Some stuff specific to my app (include the worker files, etc..)
*/
$result = ob_get_contents(); // Get the wrote things and save them to DB as result
$this->worker->setResult($result);
$this->worker->setPercent(100);
ob_end_clean();
}
}
Это немного сложно, но у меня не было выбора, так как у меня нет доступа к серверным плагинам и библиотекам.
В идеале это можно сделать с помощью бэкэнда очереди / рабочего. Но для этого требуется, чтобы вы могли настраивать постоянные фоновые задачи на сервере. Не похоже, что это возможно. Возникает вопрос, какие именно возможности делать и не у вас есть?