我为我的 Rails 应用程序运行 4 个 Unicorn 进程,它们耗尽了所有可用的 MySQL 连接,导致它因“连接过多”错误而崩溃。今天我不得不重启我的数据库实例 4 次。 =(

进程

$ 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 
... 

Unicorn 配置 文件如下所示:

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 

如果我们查看数据库控制台,我们会看到类似这样的内容。他们已经吃掉了大部分的联系。 (此刻我只有 Unicorn 在运行)在我看来应该有 1 个连接 * 4 个 unicorn = 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

请您参考如下方法:

您已经运行了 4 个 unicorn 进程。这是进程,不是线程。
每个进程在池中有 22 个连接。他们总共有 22*4 = 88 个连接。
如果你想为 4 个工作进程有 4 个连接,你可以在 database.yml 中设置 pool: 1


评论关闭
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!