2009-06-12 48 views
3

每當新用戶在我的網站上註冊時,我想要做一些預處理以縮短他們在將來的搜索。這需要30到2分鐘的處理時間。很明顯,當他們點擊註冊時的提交按鈕...或者他們訪問的任何PHP頁面時,我都無法做到這一點。但是,我希望在簽署(或更少)的5分鐘內完成此操作。PHP-在用戶註冊時需要一個cron進行後臺處理......(或分叉進程)

克朗路線 我想這需要在cron作業,如果是的話,我應該如何設置cron作業?如果是這樣,我的cron行應該每2分鐘運行一次,我如何確保我沒有與下一個cron作業重疊?

事件/叉路線 - 首選 如果我能有可能拋出一些事件到我的服務器,而不破壞我的用戶體驗或創建一個進程關閉用戶註冊(而不是cron作業),我怎麼能做到這一點的?

回答

5

我會建議既不解決。

取而代之的是,你可能最好用一個長期運行的進程(守護進程)從message queue獲取它的工作。如果這是您的首選方法,則消息隊列本身可能不在數據庫中。

您會將作業的標識符發佈到您的數據庫,然後一個長時間運行的過程會在一段時間內遍歷它們並對其執行操作。

這是非常簡單:

<?php 
while(true) { 
    jobs = getListOfJobsFromDatabase(); // get the jobs from the databbase 
    foreach (jobs as job) { 
     processAJob(job); // do whatever needs to be done for the job 
     deleteJobFromDatabase(job); //remember to delete the job once its done! 
    } 
    sleep(60); // sleep for a while so it doesnt thrash your database when theres nothing to do 
} 
?> 

而只是運行在命令行該腳本。

這比cron工作的好處是你不會得到競爭條件。

您可能還想分離實際處理的作業,這樣可以並行處理多個作業,而不是按順序處理。

+0

我怎麼能保證,這是運行的,如果它崩潰,恢復和重新啓動呢? – MichaelICE 2009-06-12 01:18:48

+0

您可以將其封裝在一個shell腳本的循環中。這樣,當它終止時,通過崩潰或其他方式,shell腳本將重新啓動它。 – Matt 2009-06-12 01:21:54

+0

Shoudl我通過一個小時cron產生了這個(只在沒有運行時才運行?) – MichaelICE 2009-06-12 01:40:07

-1

這是我的想法。爲所有用戶提供一個cron。通過這種方式,您可以通過將它們放入像隊列一樣工作的表中來確保不會發生重疊。每小時運行一次cron,但如果隊列不爲空,請先檢查隊列。如果它不跳過一小時的cron工作,請再試一次。

2

您可以使用以下類來調用背景PHP任務。

class BackgroundProcess { 
    static function open($exec, $cwd = null) { 
     if (!is_string($cwd)) { 
      $cwd = @getcwd(); 
     } 

     @chdir($cwd); 

     if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { 
      $WshShell = new COM("WScript.Shell"); 
      $WshShell->CurrentDirectory = str_replace('/', '\\', $cwd); 
      $WshShell->Run($exec, 0, false); 
     } else { 
      exec($exec . " > /dev/null 2>&1 &"); 
     } 
    } 

    static function fork($phpScript, $phpExec = null) { 
     $cwd = dirname($phpScript); 

     if (!is_string($phpExec) || !file_exists($phpExec)) { 
      if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { 
       $phpExec = str_replace('/', '\\', dirname(ini_get('extension_dir'))) . '\php.exe'; 

       if (@file_exists($phpExec)) { 
        BackgroundProcess::open(escapeshellarg($phpExec) . " " . escapeshellarg($phpScript), $cwd); 
       } 
      } else { 
       $phpExec = exec("which php-cli"); 

       if ($phpExec[0] != '/') { 
        $phpExec = exec("which php"); 
       } 

       if ($phpExec[0] == '/') { 
        BackgroundProcess::open(escapeshellarg($phpExec) . " " . escapeshellarg($phpScript), $cwd); 
       } 
      } 
     } else { 
      if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { 
       $phpExec = str_replace('/', '\\', $phpExec); 
      } 

      BackgroundProcess::open(escapeshellarg($phpExec) . " " . escapeshellarg($phpScript), $cwd); 
     } 
    } 
} 

使用這樣:

BackgroundProcess::fork('process_user.php');