2012-06-28 25 views
13

我正在使用rufus-scheduler來運行一些頻繁的工作,它們使用ActiveRecord對象執行一些各種任務。如果有任何形式的網絡或postgresql打嗝,即使在恢復後,所有線程都會拋出以下錯誤,直到進程重新啓動:rufus-scheduler中ActiveRecord對象的連接池問題

ActiveRecord :: ConnectionTimeoutError(無法在5秒內獲得數據庫連接(等待5.000122687秒),最大池大小目前是5;考慮增加它

錯誤可以很容易地通過重新啓動postgres重現我曾嘗試使用遊戲池大小玩(最多15),但沒有運氣。

這使我相信這些連接只是處於陳舊狀態,我認爲這將會通過撥打clear_stale_cached_connections!來解決。

有沒有更可靠的模式來做到這一點?

傳遞的塊是一個簡單的選擇和更新活動記錄調用,並且碰巧不管AR對象是什麼。

的魯弗斯工作:

scheduler.every '5s' do 
    db do 
    DataFeed.update #standard AR select/update 
    end 
end 

包裝:

def db(&block) 
    begin 
     ActiveRecord::Base.connection_pool.clear_stale_cached_connections! 
     #ActiveRecord::Base.establish_connection # this didn't help either way 
     yield block 
    rescue Exception => e 
     raise e 
    ensure 
     ActiveRecord::Base.connection.close if ActiveRecord::Base.connection 
     ActiveRecord::Base.clear_active_connections! 
    end 
    end 
+0

它的任何更新? – jbmyid

+0

我也面臨同樣的問題,上面嘗試,甚至「ActiveRecord :: Base.connection_pool.with_connection」做但不工作 – jbmyid

回答

-1

我真的不知道魯弗斯調度,但我得到了一些想法。

第一個問題可能是rufus-scheduler上的一個錯誤,它沒有正確檢查數據庫連接。如果是這種情況,唯一的解決方案是像你已經手動清除陳舊的連接,並通知rufus-scheduler的作者關於你的問題。

可能發生的另一個問題是您的DataFeed操作需要很長時間,並且因爲它每5次執行一次,Rails將用盡數據庫連接,但這不太可能。

1

原因可能是你有許多線程正在使用所有連接,如果DataFeed.update方法花費的時間超過5秒,那麼你的塊可能會重疊。

嘗試

scheduler.every("5s", :allow_overlapping => false) do 
#... 
end 

也儘量釋放連接,而不是關閉它。

ActiveRecord::Base.connection_pool.release_connection 
11

Rufus調度程序爲每個作業啓動一個新線程。另一方面ActiveRecord不能共享線程之間的連接,所以它需要分配一個連接到特定的線程。

當你的線程還沒有連接,它會從池中獲得一個。 (如果池中的所有連接都在使用中,它將一直等到一個線程從另一個線程返回,最終超時並拋出ConnectionTimeoutError)

當您完成後,您有責任將其返回池中它在Rails應用程序中自動完成。但是如果你正在管理你自己的線程(就像rufus那樣),你必須自己來完成。

Lucklily,對於這樣的一個API: 如果你把你的代碼with_connection塊內,它會得到一個連接形成池,並釋放它,當它完成

ActiveRecord::Base.connection_pool.with_connection do 
    #your code here 
end 

你的情況:

def db 
    ActiveRecord::Base.connection_pool.with_connection do 
    yield 
    end 
end 

應該做的伎倆....

http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/ConnectionPool.html#method-i-with_connection