我使用的是鲁弗斯调度运行一个数字,做一些不同的任务与ActiveRecord对象频繁跳槽的。 如果有任何形式的网络或PostgreSQL打嗝,即使恢复后,所有的线程会抛出下面的错误,直到进程重新启动:
的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
鲁弗斯调度开始每一项工作一个新的线程。 ActiveRecord的,另一方面不能共享线程之间的连接,所以它需要分配给特定线程的连接。
当你的线程没有连线,它会得到一个从池中。 (如果池中的所有连接都在使用,它会等待,直到一个是从另一个线程返回。最终超时和投掷ConnectionTimeoutError)
这是你的责任,将其返回到池中,当你用它做,在一个Rails应用程序,这是自动完成的。 但是,如果你正在管理自己的线程(如鲁弗斯那样),则必须将此自己做。
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
其原因可能是,你有哪些正在使用的所有连接多个线程,如果DataFeed.update
方法需要超过5秒,比你的块可以重叠。
尝试
scheduler.every("5s", :allow_overlapping => false) do
#...
end
也可以尝试释放连接,而不是关闭它。
ActiveRecord::Base.connection_pool.release_connection
我真的不知道鲁弗斯调度,但我得到了一些想法。
第一个问题可能是对鲁弗斯调度不正确检出数据库连接的错误。 如果是这种情况的唯一解决办法是手动清除陈旧的连接,你已经做的,并告知鲁弗斯调度的作者您的问题。
可能发生的另一个问题是,你的数据传送专线操作需要很长的时间,因为它是每5个secondes Rails的已经不多了数据库连接进行的,但它是相当不可能的。