【问题标题】:Yii Php Executing asynchronous background requestYii Php 执行异步后台请求
【发布时间】:2014-10-09 03:34:27
【问题描述】:

您好,我正在尝试在后台执行 LONG RUNNING 请求(操作)。

function actionRequest($id){

//execute very long process here in background but continue redirect

Yii::app()->user->setFlash('success', "Currently processing your request you may check it from time to time.");
$this->redirect(array('index', 'id'=>$id));
}

我想要实现的是不让用户等待处理请求,因为它通常需要 5-10 分钟,并且请求通常会进入 超时,即使我将超时设置得更长,也要等待 5-10 分钟。不是很好的用户体验。

所以我想立即返回页面通知用户他/她的请求正在处理中,而他仍然可以浏览,并在应用程序中做其他事情,然后他/她可以返回页面查看他/她的请求是否已处理。

我查看了 Yii 扩展 backjob,它可以工作,重定向会立即执行(不知何故是后台请求),但是在做其他事情时,比如在网站中导航,它不会加载,而且看起来请求仍然存在,并且在请求完成之前我无法继续使用该应用程序。

一个类似的扩展 runactions 承诺同样的事情,但我什至无法让它工作,它说它“触及一个 url”,就像火灾和忘记工作但不起作用。

我也尝试过像GearmanRabbitMQ 这样的消息队列服务,但它的技术含量非常高,我什至无法在我的 Windows 机器上安装 Gearman,所以“农场”服务无法正常工作我。后台处理的一些答案包括 CRON 和 AJAX,但这听起来不太好,还有很多问题。

是否有任何其他解决方法来进行异步后台处理?我真的为此努力过,而且我真的不是在寻找高级/复杂的解决方案,例如“将工作外包给几台机器”之类的。非常感谢!

【问题讨论】:

    标签: php asynchronous yii request background-process


    【解决方案1】:

    如果您希望能够通过 Yii 运行异步作业,您可能别无选择,只能尝试一些 AJAX 以异步检索作业的状态。以下是对我有用的高级指南。希望这会对您有所帮助!


    设置控制台操作

    要运行后台作业,您需要使用 Yii 的控制台组件。在 /protected/commands 下,创建一个包含您的 actionRequest() 的 Web 控制器副本(例如 /protected/commands/BulkCommand.php)。

    这应该允许您进入 /protected 文件夹并运行 yiic bulk request

    请记住,如果您之前没有创建过控制台应用程序,则需要设置其配置,就像您为 Web 应用程序所做的那样。将 /protected/config/main.php 直接复制到 /protected/config/console.php 应该可以完成 90% 的工作。


    自定义扩展以运行异步控制台作业

    对我有用的是结合使用两个扩展:CConsoleTConsoleRunner。 TConsoleRunner 使用 popen 运行 shell 脚本,这在 Windows 和 Ubuntu 上对我有用。我只是将它的 run() 代码合并到 CConsole 中,如下所示:

    public function popen($shell, $redirectOutput = '')
    {
        $shell = $this->resolveCommandLine($shell, false, $redirectOutput);
        $ret = self::RETURN_CODE_SUCCESS;
        if (!$this->displayCommands) {
            ob_start();
        }
    
        if ($this->isWindows()) {
            pclose(popen('start /b '.$shell, 'r'));
        }
        else {
            pclose(popen($shell.' > /dev/null &', 'r'));
        }
    
        if (!$this->displayCommands) {
            ob_end_clean();
        }
        return $ret;
    }
    
    protected function isWindows()
    {
        if(PHP_OS == 'WINNT' || PHP_OS == 'WIN32')
            return true;
        else 
            return false;
    }
    

    之后,我将 CConsole 的 runCommand() 改成如下:

    public function runCommand($command, $args, $async = false, &$outputLines = null, $executor = 'popen')
        {
            ...
            switch ($executor) {
                ...
                case 'popen':
                    return $this->popen($shell);
                ...
            }
        }
    


    运行异步作业

    通过上述设置,您现在可以使用以下 sn-p 代码调用我们之前创建的yiic bulk request

    $console = new CConsole();
    $console->runCommand('bulk request', array(
        '--arg1="argument"',
        '--arg2="argument"',
        '--arg3="argument"',
    ));
    

    你可以在你原来的 actionRequest() 中插入这个。


    检查状态

    很遗憾,我不确定您的批量请求在做什么。对于我自己,我收集了一大堆文件并将它们放在一个文件夹中。我知道我期望输入多少文件,因此我可以轻松地创建一个控制器操作来验证到目前为止已经创建了多少文件,并将状态的 % 表示为一个简单的除法。

    【讨论】:

      猜你喜欢
      • 2011-11-27
      • 1970-01-01
      • 2012-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多