我在Sinatra中创建了一个小聊天应用程序,在heroku上创建了jQuery。它只是在用户提交时将消息插入数据库。并且还每2秒下载一次新消息。经过几分钟的测试后,它停止了工作,我收到了一封来自heroku的电子邮件:
您好,
我们注意到gisekchat应用程序有大量连接 打开共享数据库。我们必须限制连接数 由于性能原因导致共享数据库。你能吗? 减少共享数据库的总连接数或移动到 专用数据库?
看起来您似乎没有利用连接池 并为每个请求打开一个新的数据库连接 你的应用。
谢谢, -Chris
这是支持提交消息的动作(接收非常相似):
post '/send' do
con = con = PGconn.connect($dbhost, 5432, "","",$dbname, $dbuser, $dbpass)
con.exec("insert into messages(usr, msg, date) values('#{params[:usr]}','#{params[:msg]}', now())")
end
如何更改它以启用连接池?
答案 0 :(得分:6)
是的,确实如此,每次发送“发送”帖子时,您确实正在打开与数据库的新连接。
所以你需要改变它。一种可能性是,在全球范围内打开连接:
$con = PGconn.connect($dbhost, 5432, "","",$dbname, $dbuser, $dbpass)
这应该在初始化$ dbname ...变量之后但在使用任何路由之前完成。
但是,如果您使用模块化sinatra版本而不是经典版本,则可以使用
声明实例变量attr_accessor :con
并在应用启动之前初始化它。
答案 1 :(得分:4)
罗布斯图斯就在那里 创建实例变量将为您的每个类实例创建一个连接。
你想要的是一个线程安全的数据存储api,它将使用互斥锁来处理对你的连接对象的访问。这是ActiveRecord在rails中使用的控制机制。
我创建了一个名为'q'的ruby gem,它为这样做提供了一种简单的机制。 宝石位于这里: https://github.com/jacobsimeon/q
像这样安装
git clone https://github.com/jacobsimeon/q
然后将此添加到任何文件初始化您的应用程序:
require 'q/resourcepool'
然后,在初始化期间创建数据存储区:
class DataConnection < ResourcePool
def create_resource
PGConn.connect(@config)
end
end
@datasource = ResourcePool.new(your_connection_info_here)
然后,您可以使用@datasource对数据库执行命令
post '/send' do
@datasource.exec(standard_postgres_params)
end
如果你对这条路线感兴趣,可以通过github或twitter(两者都是@jacobsimeon)与我联系。
答案 2 :(得分:1)
我使用了'经典'sinatra应用程序,并通过声明类变量获得了相同的结果:例如@@ db_connection。这总是使用相同的连接,对我有用。