2010-01-29 60 views
1

我已經做了一些谷歌搜索這個主題,並找不到我的問題的答案。php異步調用,並從後臺作業獲得響應

我想實現的是以下幾點:

  1. 客戶端進行異步調用的函數的服務器
  2. 服務器在後臺運行該函數(因爲該函數是耗時)和客戶端沒有掛在其間
  3. 客戶端不斷向服務器請求後臺作業狀態的呼叫

可以請你給我解決我的問題的一些建議?

非常感謝!^-^

回答

0
  1. Ajax調用run方法longRunningMethod(),並取回一個idendifier(例如一個id)
  2. 服務器上運行的方法,並設置鍵如sharedmem
  3. 客戶端調用checkTask(ID)
  4. 服務器查找在sharedmem鍵和檢查就緒狀態 [重複3 & 4至5結束]
  5. longRunningMethod完成,並設置狀態sharedmem到成品。

所有Ajax調用按定義都是異步的。

+0

它的作品,但醜陋,不方便!當討論線程時,我討厭php。 – 2015-01-16 05:12:16

3

你沒有指定異步調用的語言,但我假設PHP兩端。 我覺得最優雅的方式是這樣的:

  • HTML頁面加載,定義了一個隨機密鑰的操作(例如,使用rand()或已經可用的會話ID [不過要小心的是,同一個用戶可能已開始兩個操作])

  • HTML頁面,使Ajax調用PHP腳本來start_process.php

  • start_process.php執行exec /path/to/scriptname.php的啓動過程;關於如何在後臺啓動進程的建議,請參閱User Contributed Notes on exec()。哪一個適合你,主要取決於你的操作系統。

  • long_process.php頻繁寫入其狀態爲狀態文件,你的Ajax頁面生成

  • HTML頁面隨機密鑰而得名使得以show_status.php讀出狀態文件,並返回進度頻繁調用。

+1

如果你想要一個由會話創建的進程的唯一標識符,那麼比rand()更安全和更明顯的候選者將是會話ID。此外,Contributed Notes中引用的代碼將以不可預知的方式在非Microsoft系統上失敗。 – symcbean 2010-01-29 10:46:07

+0

乾杯symcbean,好點。我編輯了我的答案。 – 2010-01-29 11:16:45

0

你可以(雖然不是絕對必要的步驟)使用AJAX來實例調用,那麼腳本可以創建在共享內存中後臺作業的狀態的引用(甚至是臨時入境SQL表,甚至臨時文件),並以唯一作業ID的形式顯示。

該腳本可以啓動後臺進程並立即將作業ID返回給客戶端。

客戶端然後可以重複地調用服務器(例如,通過另一個AJAX接口)來查詢作業的狀態,例如, 「進行中」,「完成」。

如果要執行的後臺進程本身是用PHP編寫的(例如命令行PHP腳本),那麼您可以將作業ID傳遞給它,它可以提供有意義的進度更新回到客戶端(通過寫入相同的共享內存區域或數據庫表)。

如果執行它的過程本身不是用PHP編寫的,那麼我建議將它封裝在一個命令行PHP腳本中,以便它可以監視正在執行的進程何時完成運行(並檢查輸出是否成功)並適當地更新該任務的狀態條目。

注意:爲此使用共享內存是最佳實踐,但如果您使用共享主機,則可能無法使用。不要忘記你想有一種方法來清理舊的狀態條目,所以我會爲每個條目存儲「started_on」/「completed_on」時間戳值,並刪除舊數據的條目(例如,具有已完成的時間戳記超過X分鐘 - 而且,理想情況下,它還會檢查前一段時間開始的工作,但從未標記爲已完成並提醒他們注意。

2

對於長時間運行的PHP進程有一個谷歌(需要警告,關於該主題有很多不好的建議 - 包括佩卡提到的說明 - 這將在微軟工作,但將在其他任何事情上以不可預測的方式失敗)。

你可以開發一個通過套接字響應請求的服務(你的客戶端會使用fsockopen進行連接) - 一些簡單的實現方法是使用Aleksey Zapparov的Socket服務器(http://www.phpclasses.org/browse/package/5758.html)處理通過然而,由於它作爲一個單線程運行,因此它可能不適合需要大量處理的東西。或者,如果您使用的是非Microsoft系統,那麼您可以將腳本掛起[x] inetd,但是您需要做一些巧妙的事情,以防止它在客戶端斷開連接時終止。

爲了在客戶端斷開連接後繼續運行,PHP代碼必須從獨立的PHP可執行文件(而不是通過Web服務器)運行。在新進程組中生成進程(請參閱posix_setsid()和pcntl_fork())。要使客戶端回來並檢查進度,最簡單的方法是將服務器配置爲將其狀態寫入客戶端可以讀取的地方。

C.