您好,我正在尝试在后台执行一个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 promise 同样的事情,但我什至无法让它工作,它说它“触及一个 url”,就像火灾和忘记工作但不起作用。
我还尝试研究消息队列服务,例如 Gearman , RabbitMQ ,但它确实技术含量很高,我什至无法在我的 Windows 机器上安装 Gearman,因此“农业”服务对我不起作用。后台处理的一些答案包括 CRON 和 AJAX,但这听起来不太好,而且还有很多问题。
是否有任何其他解决异步后台处理的方法?我真的为此努力寻找,我真的不是在寻找高级/复杂的解决方案,如“将工作分包给多台机器”等。非常感谢!
最佳答案
如果您希望能够通过 Yii 运行异步作业,您可能别无选择,只能尝试使用一些 AJAX 以异步检索作业的状态。以下是对我有用的高级指南。希望这会以某种方式帮助您!
设置控制台操作
要运行后台作业,您需要使用 Yii 的控制台组件。在/protected/commands 下,创建一个包含 actionRequest() 的网络 Controller 副本(例如/protected/commands/BulkCommand.php)。
这应该允许您进入/protected 文件夹并运行 yiic bulk request
。
请记住,如果您之前没有创建过控制台应用程序,则需要像为 Web 应用程序那样设置它的配置。将/protected/config/main.php 直接复制到/protected/config/console.php 应该可以完成 90% 的工作。
自定义运行异步控制台作业的扩展
对我有用的是结合使用两个扩展名:CConsole和 TConsoleRunner . 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);
...
}
}
运行异步作业
通过以上设置,您现在可以使用以下代码片段来调用我们之前创建的 yiic 批量请求
。
$console = new CConsole();
$console->runCommand('bulk request', array(
'--arg1="argument"',
'--arg2="argument"',
'--arg3="argument"',
));
您可以将其插入到原始的 actionRequest() 中。
检查状态
很遗憾,我不确定您的批量请求在做什么工作。对于我自己,我正在收集一大堆文件并将它们放在一个文件夹中。我知道我希望输入多少文件,所以我可以轻松地创建一个 Controller 操作来验证到目前为止已经创建了多少文件,并将 % 的状态作为一个简单的除法。
关于php - Yii Php 执行异步后台请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26269872/