2010-10-21 80 views
4

我們正在做一些新應用的原型設計,並注意到其中一項操作需要永久加載(80-120秒)。由於很多處理不需要在頁面加載時發生(我們可以稍後通過Ajax請求數據),所以我想使用Process.fork來允許頁面立即返回,而處理仍然在「幕後」進行。Rails控制器中的Process.fork

我們使用Apache與Passenger爲應用程序。

幾件事情:

  1. 我知道delayed_jobs,resque,BJ等後臺作業的寶石。我們使用dj,並且最終會使用類似的東西來實現這一點。這是我們原型設計時的權宜之計。

  2. 我不關心服務器的性能。該應用程序運行在自己的服務器上,只有少數用戶試用它。

早期測試表明這很好,但我想知道這是否是一個好主意。它會變得可靠嗎?如果用戶導航到另一個頁面,或者關閉標籤頁/瀏覽器,分叉過程是否會繼續? fork完成後,進程是否會自行終止?

回答

5

取決於「處理」的含義。 一般來說,如果處理意味着使用Rails堆棧,這並不可靠 - 因爲由請求釋放的主進程可能會被乘客分配給另一個請求,並且事情可能會出錯。 此外,Passenger可能會在某些情況下關閉主進程並因此關閉Rails實例(減少空閒實例池等)。

一般來說,這可能會導致進程泄漏,意外鎖,競爭條件,應用程序錯誤而停機等

我建議使用Apache /客運棧外運行工人,例如使用集羣BackgrounDRb或其他解決方案(您提到Resque)。

還有一個想法,我目前使用我的應用程序的cron作業。我的crontab只有幾個wget來處理長時間運行的任務。您可以按需要在紅寶石叉子上做類似OpenURI的事情。想象一下應用程序通過HTTP pinging本身。分叉進程不再需要Rails - 它只是訪問任務頁面,然後Passenger爲此特殊請求提供服務請求並管理應用程序實例。

如果乘客殺死了fork的父代並因此分叉進程 - 另一個Rails實例應該繼續處理http請求。

+0

很好的答案,謝謝。這是我正在尋找的信息 - 我對乘客查殺過程感到好奇等等。問題是,在我們進行原型設計時,我不想花費大量的時間或精力設置後臺處理。雖然我們最終會使用DJ,BackgrounDRb,Resque或類似的技術,但在這種情況下它們都是過度的。我只想返回頁面,同時執行一個單一的模型動作,用數據填充一些數據庫表。 – vonconrad 2010-10-21 12:38:46

+0

我用另一個想法編輯了答案。 – gertas 2010-10-24 18:34:36

0

是的,只要您使用之前已經過測試和使用的寶石,它就是可靠的。 DelayedJobs和Spawn(我經常使用)都已經存在了相當長的一段時間,應該完全按照你期望的那樣去做。

由於該過程在服務器的後臺運行,因此如果用戶關閉了沒有客戶端附件的選項卡/瀏覽器,它應該會繼續良好。當程序完成執行時,它將自行終止並釋放內存。

你可以閱讀更多關於分叉這個優秀wiki-page。作爲一個側面說明,不要在Rails中使用ruby fork方法,因爲這對ActiveRecord並不會很好。

+0

恐怕你沒有真的看過我的問題......我知道DJ,Spawn和其他寶石,但是如果我們能夠在原型製作的時候想避免使用它們,我特別要指出的是,只是使用'Process.fork'會導致問題 - 本質上是在最後一段中將您的「旁註」作爲您答案的要點。你想介紹一下嗎? – vonconrad 2010-10-21 12:32:34

+1

我可能沒有得到它,但產卵需要沒有實現;你唯一要做的就是調用spawn並給它一個在後端執行的塊。這幾乎不會花費你幾個小時的時間。分叉的問題在於,據我所知,ActiveRecord在分叉中不可用。我不知道技術細節,但這就是爲什麼Spawn被創建與其他代碼分離的原因。 – Maran 2010-10-22 11:44:19

0

只是想編鐘,以防谷歌把你帶到這裏。在Passenger> v4.0中,有一種方法可以通過使用「帶外工作」來實現。我用它長長的任務,比如像這樣在西納特拉控制器發送電子郵件:

# Your app should tell Passenger about this OOB task, won't run otherwise 
headers['X-Passenger-Request-OOB-Work'] = "true" 
PhusionPassenger.on_event(:oob_work) do 
    # The following line takes a while to run, 
    # but won't tie up any http-serving processes 
    mail.deliver! 
end 

的信息可以在這裏找到:http://blog.phusion.nl/2013/01/22/phusion-passenger-4-technology-preview-out-of-band-work/

以前,我一直在使用Process.fork試了又試殺死進程後來;雖然這實際上完成了第一部分,但事實上它並不會真正殺死分叉進程,而乘客最終會吃掉所有可用的內存(正如我在生產系統中精心設計的)。顯然,無法編程來拯救我自己的生活。

希望這會有所幫助!