2015-03-31 42 views
0

我需要異步調用循環中的PHP方法。異步PHP調用類方法

這是我的嘗試:

foreach ($batch_ids as $batch_id) { 
      $this->launchBackgroundProcess($this->sendBatchMail($batch_id)); 
     } 

public function launchBackgroundProcess($call) { 

    // pclose(popen($call.'/dev/null &', 'r'));  
    Proc_close(Proc_open($call.' > /dev/null & ', 'r')); 
    return true; 
} 

現在的錯誤是,我的功能sendBatchMail被直接調用和launchBackgroundProcess不會被調用(使用回聲/打印/日誌查詢)。

所以如果在一個批處理id中有10k個郵件,下一批id的endBatchcMail永遠不會啓動。

我希望在後臺爲所有批處理標識符retreived同時並異步調用sendBatchMail。

我並不十分精通pthreads ......並且似乎是我的最後一站。

回答

1

這不是真的要走的路。每個PHP進程都會針對每個單獨的請求啓動並拆除。您不應該試圖直接從PHP腳本中直接啓動任何應用程序來回應HTTP請求。它唯一的工作應該是儘快返回HTTP響應,然後掛斷。任何大量的工作應該排隊等待稍後持久的後端工作人員處理。

這直接把我帶到消息隊列和工作人員。看看Gearman是一個非常簡單的系統,不過還有很多其他的可能性,包括ØMQ,Redis等。您只需在該隊列中填入大量消息,然後將由後臺中的一個或多個作爲cron作業或持久worker守護程序運行的PHP腳本進行處理,這些腳本完全與前端HTTP處理程序分離。要做到這一點

+0

非常感謝。我這個運行郵件的php方法本身是通過cron執行的。但我希望這最終可以同步batch_id調用。將通過鏈接進一步瞭解您的建議。 – zeetit 2015-03-31 08:04:19

+0

基本上你想要*並行運行多個進程*。 「異步性」只是切線。由於PHP並不是一種真正的異步語言,因此實現此目標的最佳方式是通過運行的工作人員數量來控制並行進程的數量,並通過消息隊列控制這些工作人員從哪裏獲得工作。 – deceze 2015-03-31 08:06:51

1

一種方式是具有與發送代碼一個PHP腳本,然後執行:

shell_exec("theBackgroundScript.php >/dev/null &"); 

但它意味着你將有很多的過程在同一時間。另外,如果其中一個出於某種原因失敗,找到並再次運行它很複雜。

相反,請考慮在數據庫中創建一個表來保存所有郵件作業。這可能是這樣的:

CREATE TABLE email_jobs (
id INTEGER AUTO_INCREMENT PRIMARY KEY, 
executed TINYINT DEFAULT 0, 
destination VARCHAR(255) NOT NULL, 
subject VARCHAR(255) NOT NULL, 
content TEXT NOT NULL, 
created_at DATETIME NOT NULL, 
updated_at DATETIME DEFAULT NULL); 

然後,你只需要在您需要時添加每項工作的細節:

$db->query("INSERT INTO email_jobs (destination, subject, content, created_at) VALUES ('[email protected]', 'some subject', 'some email content', NOW())"); 

然後,你需要一個PHP腳本,將查詢工作數據庫尚未執行:

$row = $db->query("SELECT * FORM email_jobs WHERE executed = 0 LIMIT 1"); 
// ... send email described in $row 

該腳本獲取第一個未執行的作業(或前N個未執行的作業),併發送它。 然後,您只需要將腳本放入cron並讓它發送所有電子郵件。

如果發生故障,再次發送很容易,只需將執行設置爲零,然後發送。

+0

您的shell_exec解決方案對我來說完美無瑕。非常感謝! – 2015-04-27 16:29:49