首页 > 解决方案 > 请求启动后台 php 脚本

问题描述

我目前正在一个显示大量统计数据的内部网站上工作,由于数据量大,一些页面或 ajax 脚本非常慢。

我正在搜索的是一种通过请求在后台启动这些脚本的方法,然后启动 ajax 请求以了解后台脚本的进度。

有什么办法可以做到这一点?我使用 php7.0 和 apache2 服务器(我无法直接访问 apache 服务器配置,所以如果可能,我会搜索客户端选项)

标签: phpapache

解决方案


如果有人正在寻找实现这一目标的方法,这是我找到的解决方案:

我在 Ajax 中调用了一个脚本,它分叉自己并将子进程的 PID 保存在数据库中。然后我在子进程中调用 session_write_close() 以允许用户发出新请求,并且父进程退出(不等待子进程结束)。当父亲退出时,用户收到他的请求的答复,子进程继续他的工作。

然后在Ajax中我调用另一个脚本来获取worker的进化,最后我得到结果并在一切完成后杀死子进程。

这是我的工人阶级的代码:

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();
    }
}

这有点棘手,但我别无选择,因为我无法访问服务器插件和库。


推荐阅读