我为我的 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