2010-07-14 121 views
1

我有一個rails應用程序,偶爾需要做非常慢的網絡調用(可能永遠不會返回)基於web用戶擊中路線。如果調用比正常情況慢(或不返回),Rails似乎會阻止,不允許任何其他事情發生(我無法打開另一個瀏覽器並選擇不同的路由,我無法使用另一臺機器不同的路線,沒有)。如何使Rails非阻塞?

我嘗試使用Phusion Passenger來處理多線程(假設它是一個雜種服務器問題),而Apache可以處理進入無限循環(而Mongrel不能)的測試控制器,似乎每個經常(當網絡呼叫不回來時),它仍然阻塞。我無法真正複製這個,所以它不是全部可測試的:

是RAILS本身阻塞,還是Apache不是正確的服務器?如果它是軌道,是否有任何我可以做的,以阻止其他用戶打開自己?

回答

2

通常情況下,如果您不得不做一些長期運行或有問題的可靠性工作,您將希望使用單獨的工作進程而不是嘗試在請求中內聯它。嘗試類似workling開始,也許RabbitMQ變得嚴重。

+0

我也應該注意到這與Rails沒有任何關係。如果您的請求需要永久返回並且用盡所有應用程序進程(幾乎以任何語言),那麼最終會出現此問題。最近對'evented'web服務器的主流化在某種程度上是對此的迴應(例如,參見nodejs.org)。 – rfunduk 2010-07-19 19:19:44

3

因爲Ruby(截至1.8)是單線程的(見here),所以Rails本身被阻塞。我們解決這個問題的方式就是運行Rails的多個副本,並將它們加載到nginx後面。但是,由於nginx與Apache的功能相同,因此如果您運行Rails的X副本,在從不返回的路由被命中X次後,您將遇到目前遇到的同樣問題。

你可能會使用nginx或apache並將其配置爲僅保持連接存活60秒 - 也許這將從永不返回路由恢復連接,並仍然允許該計算儘管無阻礙地發送(即不發送連接重置爲導軌)。

+1

右:我已經知道了,這就是爲什麼我使用Passenger和Apache(Passenger會自動創建多個鋼軌副本)。我的沮喪是DESPITE,它仍然偶爾搞砸了。 – Jenny 2010-07-19 19:27:52

3

我們將任何可能需要一兩秒鐘時間的調用移動到優先級隊列才能異步處理。我們使用delayed_job (the collectiveidea branch)來處理所有後臺作業,但是最近流行的另一個作業是resque,我沒有使用它,並且除了它的基本功能之外,我不能說出它。

從那裏你可以使用ajax來查詢工作狀態,同時顯示一個進度條,一個微調框或者一個罐頭吃烤土豆 - 直到工作完成。通過這種方式,後臺和網絡前臺的後臺作業流程將保持活潑。

流程將是:

  1. 用戶提交請求
  2. 請求排隊
  3. 前端響應
  4. 網絡操作開始
  5. 網絡操作結束
  6. 在客戶
  7. 開始投票
  8. 後臺作業完成
  9. 民意調查得到迴應和更新UI

VS.

  1. 用戶提交請求
  2. 網絡操作開始
  3. 網絡操作結束
  4. 前端響應

這比獲得/處理/顯示你的標準收費,但更復雜一點當您有長時間運行的流程時,這是處理它們的理想方法。這是一個例子,它是Mint.com。當它更新你的銀行賬戶時,你可以點擊整個網站,當它完成時,你會收到通知。

如果你不能走這條路線,那麼你只需要增加前端處理傳入請求的進程數。我們正在遷移到unicorn,但passenger應該有效確保您忙碌的員工不會收到新的請求。我建議這只是作爲最後的手段 - 你的請求應該都在一秒鐘或最多兩次響應,其他所有內容都應該發送到後臺作業處理器。

0

這可能會也可能不會幫助,但是...如果用戶正在進行的呼叫可以立即返回(即,不要等待那麼長的網絡呼叫返回),那麼您可能想要返回嘗試處理關閉網絡呼叫到一個單獨的進程。我所看到的是運行一個單獨的「服務器」進程(1),它接受來自主(Web服務器)進程的調用來執行任務。然後,主導軌進程可以處理用戶並向輔助進程發送訂單以進行網絡呼叫。

的原因獨立進程來處理網絡電話是雙重的:

  1. 在一般情況下,單獨的進程有很多較少的內存,所以如果你想叉可以不停的自身情況快很多爲每個網絡呼叫。
  2. 如果單獨的進程確實鎖定,它不會停止主要的Web服務器。
3

JRuby使用本地線程並不會阻止MRE或REE的方式。 JRuby on Rails應用程序可輕鬆部署到Glassfish或Torquebox,使用warbler創建部署到任何Java服務器(如Tomcat)的.war文件並不那麼困難。此外,您不必旋轉n副本的Rails堆棧以處理n請求。

我正在做後者,它很好。