2013-02-15 19 views
2

我有一個從其他網站獲取數據的功能,需要30秒才能完成。我需要這個函數來執行來自用戶的web請求,但不希望他等待那個時間。如何在Rails中的Web請求中對長進程進行子線程化處理

當前該方法在我的視圖控制器內調用。

我該如何讓自己的方法執行該方法,而不是讓用戶等待?

+0

如果你想顯示用戶的響應依賴於長期的過程,答案是不同的 – 2013-02-15 08:34:18

+0

沒錯,但事實並非如此。 – LouwHopley 2013-02-18 05:29:33

回答

1

如果您要顯示用戶的響應不取決於您的長進程的結果,那麼您所需要做的就是在與主請求不同的線程中執行進程。

你當然可以採取史蒂夫的方法,並使用處理隊列(delayed_job,sidekiq,resque),但這聽起來像是矯枉過正。你可以簡單地派生新subprocess並將其分離或派生新thread

pid = Process.fork do 
    long_process 
end 
Process.detach pid 
+1

我知道這已被接受爲答案,但事實並非如此。有很多方法可能會出錯。服務器可能會殺死你的進程。您的進程和主進程可能會同時嘗試使用相同的數據庫連接進行事務處理等。另請參見http://stackoverflow.com/questions/3984748/process-fork-in-rails-controller。 – 2013-02-18 21:58:15

+0

是真的,它有它的危險,但服務器如何殺死它,共享db連接有什麼問題。你介意闡述嗎?我在鏈接中看到有關AR和叉的提示,但不確定它是否是最新的擔心。 – 2013-02-18 22:22:52

+0

我不是這方面的專家,但我不需要。 Rails並不特別支持分叉,因此,即使我們不知道具體的問題,我們也無法預測它應該起作用。事實上,我們知道負載平衡器可以關閉Rails進程,從而關閉fork仍在使用的資源,並且我們知道如果共享數據庫連接恰好可以工作,則一個進程可能最終會在由另一方創建的交易,導致錯誤的結果和/或錯誤。我確信有大量的其他潛在問題 – 2013-02-18 22:48:30

1

您需要有一個處理這些請求的後臺代理。我最近使用beaneater gem和beanstalkd實現了這樣的消息隊列。我用神寶來管理後臺進程,並編寫了一個init腳本來管理上帝進程。頁面中的JavaScript每1.5秒發出一次AJAX調用來查詢請求的狀態並告訴用戶何時完成。

我後來得知上帝已知有內存泄漏,所以Bluepill可能是更好的選擇。就在今天,我還發現了http://michaelvanrooijen.com/articles/2011/06/08-managing-and-monitoring-your-ruby-application-with-foreman-and-upstart/,它描述瞭如何使用Foreman和Upstart來進行後臺進程,這看起來更加直接和強大。下一次我需要做這樣的事情,我可能會嘗試工頭/暴發戶/ beaneater/beanstalkd。

請注意,有許多不同的消息隊列可供選擇,具有不同的優缺點。 beanstalkd響應速度非常快,這對於運行花費數分鐘或更少時間的進程來說非常好。

相關問題