2013-03-11 56 views
1

我正在使用Ruby Grape創建一個API,並面臨以下問題。 當有新的GET請求時,請求大量數據,這需要很長時間,同時反應器被阻塞,並且在請求完成之前不能處理新的請求。 代碼很直截了當:紅寶石葡萄反應器被阻止

class API < Grape::API 
    resource :users do 
    get do 
     get_users() 
    end 
    end 
end 

get_users連接到另一個系統通過TCP,並得到大量轉換成JSON數據。這是使用第三方寶石完成的。 什麼是處理這種情況的最佳選擇?

回答

0

我覺得兩個選項:

  1. 設置乘客/麒麟等具有足夠的工人來處理併發請求。
  2. 如果這還不夠:重新制作API邏輯,以便長時間操作將分解爲兩個調用:第一個 - 請求,第二個 - 檢查完成/檢索結果。

而且,如果是適合的 - 你可以緩存get_users的結果()

+0

謝謝Yuriy。 1.我正在使用Thin。我正在考慮像NginX + HAProxy + Thin這樣的體系結構,其中有幾個實例。我也會檢查乘客和獨角獸。 2.我試圖用EM.defer做類似的事情。你認爲這是好方法嗎?緩存是我沒有想過的。我也會檢查。 但我認爲我更喜歡你的第二點。 – antiziclon 2013-03-11 21:18:55

+0

其實我的意思是另一回事。這裏是一個例子: 1.客戶端調用獲取用戶 2.應用程序保存此請求,並將生成的請求密鑰返回給客戶端 3.應用程序通過delayed_job或類似的方式生成get_users() 4.應用程序保存get_users()與請求密鑰關聯 5.客戶端調用通過密鑰獲取用戶 6.應用返回與密鑰關聯的結果。 當get_users()尚未完成時,應用程序應返回not_ready。 應用程序應該過期鍵和結果。 缺點是客戶必須改變它的邏輯。所以這隻適用於報表生成等非常長的操作。 – 2013-03-12 03:30:33

+0

我現在明白了。我不太喜歡這種方法,因爲它需要客戶改變其邏輯,如你所說。我會測試你的觀點1,看看我能做些什麼。 – antiziclon 2013-03-12 08:56:49

0

你的應用程序執行長時間運行的阻塞I/O操作。要很好地處理這些類型的工作負載,您的系統需要支持較高的I/O併發性。

傳統的單線程多進程系統,如Phusion Passenger開源和Unicorn不適合這些類型的工作負載。它們可以處理的併發量受限於進程的數量。這個問題記錄在獨角獸的philosophy page,「在某些情況下更糟糕」一節或最近關於tuning Phusion Passenger's concurrency的Phusion文章中。

雖然由於其I/O模型均勻,Thin理論上能夠處理高I/O併發性,但必須明確編寫應用程序和框架才能充分利用此優勢。很少有框架可以做到這一點。 Rails和Sinatra都不支持I/O。 Cramp支持它,並且還有另一個新的Evented框架,我忘記了它的名字。但看起來葡萄不支持偶數的I/O。

解決方案是切換到支持多線程的應用程序服務器,它也能夠支持高I/O併發性。一個這樣的應用服務器是Phusion Passenger 4 Enterprise,它支持混合多線程/多進程模型。多線程是併發的,而多進程是爲了穩定性和利用多個CPU核心的能力。 Phusion博客describes optimal concurrency settings for different workloads.