数据库连接池

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

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

是的,这是真的,每次发送’发送’后,你真的打开一个新的数据库连接。

所以你需要改变它。 一种可能性是,在全球范围内打开连接:

  $con = PGconn.connect($dbhost, 5432, "","",$dbname, $dbuser, $dbpass) 

这应该在初始化$ dbname …变量之后但在使用任何路由之前完成。

但是,如果您使用模块化sinatra版本而不是经典版本,则可以使用声明实例变量

 attr_accessor :con 

并在应用程序启动之前初始化它。

Robustus在那里创建一个实例变量将为您的类的每个实例创建一个连接。

你想要的是一个线程安全的数据存储api,它将使用互斥锁来处理对你的连接对象的访问。 这是ActiveRecord在rails中使用的控制机制。

我创建了一个名为’q’的ruby gem,它为这样做提供了一种简单的机制。 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两者)与我联系。

我使用了’经典’sinatra应用程序,并通过声明类变量获得了相同的结果:例如@@ db_connection。 这总是使用相同的连接,并为我工作。