2012-11-09 34 views
2

我爲我的Rails應用程序運行4個Unicorn進程,他們吃掉了所有可用的MySQL連接,導致它崩潰,導致「連接太多」錯誤。今天我不得不重啓我的數據庫實例4次。 =(獨角獸吃掉MySQL連接不尊重池大小 - Rails

流程

 
$ ps ax | grep [u]ni 
21618 ?  Sl  0:15 unicorn master -D -c /home/deployer/apps/XXX/shared/config/unicorn.rb -E production               
21632 ?  Sl  0:20 unicorn worker[0] -D -c /home/deployer/apps/XXX/shared/config/unicorn.rb -E production               
21636 ?  Sl  0:14 unicorn worker[1] -D -c /home/deployer/apps/XXX/shared/config/unicorn.rb -E production               
21640 ?  Sl  0:20 unicorn worker[2] -D -c /home/deployer/apps/XXX/shared/config/unicorn.rb -E production               
21645 ?  Sl  0:12 unicorn worker[3] -D -c /home/deployer/apps/XXX/shared/config/unicorn.rb -E production 

的database.yml是建立在ActiveRecord的池22個連接...

 
... 
production: 
    adapter: mysql2 
    encoding: utf8 
    database: xxx 
    username: xxx 
    password: xxx 
    host: xxx 
    port: 3306 
    pool: 22 
... 

而且獨角獸配置文件是這樣的:

 
working_directory "/home/deployer/apps/XXX/current" 
pid "/home/deployer/apps/XXX/shared/pids/unicorn.pid" 
stderr_path "/home/deployer/apps/XXX/shared/log/unicorn.log" 
stdout_path "/home/deployer/apps/XXX/shared/log/unicorn.log" 

listen "/tmp/unicorn.XXX.sock" 
worker_processes 4 
timeout 100 

preload_app true 

before_fork do |server, worker| 
    # Disconnect since the database connection will not carry over 
    if defined? ActiveRecord::Base 
    ActiveRecord::Base.connection.disconnect! 
    end 

    # Quit the old unicorn process 
    old_pid = "#{server.config[:pid]}.oldbin" 
    if File.exists?(old_pid) && server.pid != old_pid 
    begin 
     Process.kill("QUIT", File.read(old_pid).to_i) 
    rescue Errno::ENOENT, Errno::ESRCH 
     # someone else did our job for us 
    end 
    end 
end 

after_fork do |server, worker| 
    # Start up the database connection again in the worker 
    if defined?(ActiveRecord::Base) 
    ActiveRecord::Base.establish_connection 
    end 
    child_pid = server.config[:pid].sub(".pid", ".#{worker.nr}.pid") 
    system("echo #{Process.pid} > #{child_pid}") 
end 

如果我們查看數據庫控制檯,我們會看到類似這樣的內容。他們已經吃掉了大部分的連接。 (我除了獨角獸以外什麼都沒有運行)在我看來,應該有1個連接* 4個獨角獸= 4個連接。

 
mysql> show full processlist; 
+-----+----------+--------------------------------------------------+------------------------+---------+------+-------+-----------------------+ 
| Id | User  | Host            | db      | Command | Time | State | Info     | 
+-----+----------+--------------------------------------------------+------------------------+---------+------+-------+-----------------------+ 
| 2 | rdsadmin | localhost:31383         | NULL     | Sleep | 9 |  | NULL     | 
| 52 | level | 212.100.140.42:50683        | leveltravel_production | Query | 0 | NULL | show full processlist | 
| 74 | level | ip-10-55-10-151.eu-west-1.compute.internal:38197 | leveltravel_production | Sleep | 5 |  | NULL     | 
| 75 | level | ip-10-55-10-151.eu-west-1.compute.internal:38199 | leveltravel_production | Sleep | 8 |  | NULL     | 
| 76 | level | ip-10-55-10-151.eu-west-1.compute.internal:38201 | leveltravel_production | Sleep | 8 |  | NULL     | 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CUT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

| 157 | level | ip-10-55-10-151.eu-west-1.compute.internal:38321 | leveltravel_production | Sleep | 154 |  | NULL     | 
| 158 | level | ip-10-55-10-151.eu-west-1.compute.internal:38322 | leveltravel_production | Sleep | 17 |  | NULL     | 
| 159 | level | ip-10-55-10-151.eu-west-1.compute.internal:38325 | leveltravel_production | Sleep | 54 |  | NULL     | 
| 160 | level | ip-10-55-10-151.eu-west-1.compute.internal:38326 | leveltravel_production | Sleep | 54 |  | NULL     | 
| 161 | level | ip-10-55-10-151.eu-west-1.compute.internal:38327 | leveltravel_production | Sleep | 54 |  | NULL     | 
| 162 | level | ip-10-55-10-151.eu-west-1.compute.internal:38329 | leveltravel_production | Sleep | 42 |  | NULL     | 
+-----+----------+--------------------------------------------------+------------------------+---------+------+-------+-----------------------+ 
90 rows in set (0.15 sec) 

您也可以在sidekiq倉庫看看問題#503對於這個問題https://github.com/mperham/sidekiq/issues/503

回答

8

您已經運行4個麒麟的後臺進程。這是過程,而不是線程。
每個進程在池中有22個連接。完全他們有22 * 4 = 88個連接。
如果你想要4連接4工作進程,你可以在database.yml中設置池:1