2014-10-09 128 views
2

嗨,我試圖執行一個長期運行請求(行動)在後臺。Yii Php執行異步後臺請求

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承諾同樣的事情,但我甚至不能讓它工作,它說它'觸及一個網址',就像一場火災和遺忘的工作,但不起作用。

我也試過查看Gearman,RabbitMQ等郵件排隊服務,但技術性很強,我甚至無法在我的Windows機器上安裝Gearman,因此「農業」服務對我來說不起作用。後臺處理的一些答案包括CRON和AJAX,但聽起來不太好,還有很多問題。

有異步後臺處理有任何其他解決方法嗎?我真的很努力地尋求這個,我真的不是在尋找先進/複雜的解決方案,比如「把工作交給幾臺機器」等等。非常感謝你!

回答

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


運行異步工作

通過上述設置,您現在可以使用以下代碼片段來調用我們之前創建的yiic bulk request

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

你會在你的原始actionRequest()中插入這個。


檢查了在狀態

不幸的是,我不知道您的批量請求是做什麼樣的工作。對於我自己,我收集了大量文件並將它們放在一個文件夾中。我知道有多少文件是我期望的,所以我可以很容易地創建一個控制器動作來驗證到目前爲止創建了多少文件,並將狀態的百分比作爲一個簡單的劃分。