数据库连接池

时间:2011-11-01 19:33:28

标签: ruby database sinatra

我在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

如何更改它以启用连接池?

3 个答案:

答案 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。这总是使用相同的连接,对我有用。