2013-03-20 33 views
2

我为每个服务器运行10个Unicorn工作人员,随着时间的推移他们吃掉了所有MySQL连接,最终导致“连接太多”错误。它从10个连接开始,但逐渐增加到20个。独角兽和Rails吃掉了2个MySQL连接

当我在生产上运行以下脚本(使用SHOW PROCESSLIST)时,我可以看到每个IP(=应用程序服务器)每个都有20个连接, 10 - 令人羡慕的是独角兽工人数量的两倍。

result = ActiveRecord::Base.connection.execute 'show processlist' 
result.group_by{|i| i[2].split(':').first }.map{|k,v| [k, v.size] } 
=> [["192.168.1.2", 20], ["192.168.1.3", 20], ["192.168.1.4", 20], ... ] 

这里的database.yml中

production: 
    adapter: mysql2 
    ... 
    pool: 1 

下面是使用netstat:

# netstat -an | grep :3306 
tcp  0  0 192.168.1.2:58535 192.168.1.123:3306 ESTABLISHED 
tcp  0  0 192.168.1.2:45021 192.168.1.123:3306 ESTABLISHED 
tcp  0  0 192.168.1.2:58537 192.168.1.123:3306 ESTABLISHED 
tcp  0  0 192.168.1.2:45119 192.168.1.123:3306 TIME_WAIT 
... 

# netstat -an | grep :3306 | wc -l 
36 
# netstat -an | grep :3306 | grep ESTABLISHED | wc -l 
33 

我担心,有几个TIME_WAIT - 它不应该存在的连接应都是持久的 - 看起来工人有更多的联系。大量的免费RAM,无需交换/ OOM。

Ruby 2.0.0p0/Rails 3.2.13

这是什么原因造成的?

回答

5

好自己的连接,这要归功于@ono的建议,我发现原因是New Relic代理创建了自己的连接NewRelic::Agent::Database::ConnectionManager#get_connection

https://github.com/newrelic/rpm/blob/3.5.8.72/lib/new_relic/agent/database.rb#L158

此代码调用ActiveRecord::Base.mysql2_connection,进而调用Mysql2::Client.new,不尊重连接池设置。

时,有慢交易(具有讽刺意味的是,这个代码重载数据库甚至更多),只发生,所以编辑newrelic.yml

transaction_tracer: 
    explain_enabled: false 

,问题已经解决了!我会保持这种状态,直到New Relic修复此问题。

+0

我在New Relic的Ruby代理上工作,并想让我们知道我们在上一版本(昨天发布的3.6.0.78)中改进了这种行为。在某些分叉网络服务器(如Unicorn,Passenger)下,这些数据库连接没有被正确清理的问题。我们已经证实,情况已经不复存在。我认为你关于不尊重连接池设置的观点可能依然存在。在某些情况下(例如,应用程序通过不同的适配器与多个dbs对话)使得这很难做到,但这是我们将在下一个版本中考虑的事情。 – samg 2013-03-21 19:56:26

+0

我更新了我的宝石到3.6.0.78,并检查连接数没有变化。再次有很多连接到MySQL。我正在使用独角兽。 – anshuman 2013-03-26 13:12:30

+0

3.6.0.78为我解决了这个问题。它仍然会建立连接,只是适当地关闭它们。如果同时有很多缓慢的查询,则会有多达2个连接。为了解决这个问题,New Relic需要支持连接池。 – kenn 2013-03-26 17:09:05

0

疯狂猜测,你有一个中间件,打开连接到你的数据库服务器?运行$ rake middleware核实,sidekiq例如你是一个原因,或任何其他coponent需要你的数据库服务器

+0

好点。我只是跑'耙中间件',但它几乎是默认的,找不到除Airbrake和NewRelic之外的任何异常。 – kenn 2013-03-20 23:29:34