Ven*_* D. 18 connection-pooling heroku rails-postgresql rails-activerecord heroku-postgres
嗨,我们正在使用独角兽和Sidekiq在Heroku的Cedar堆栈上运行.我们间歇性地得到以下错误
BurnThis ActiveRecord::StatementInvalid: PG::UnableToSend: SSL SYSCALL error: EOF detected
ActiveRecord::StatementInvalid: PG::ConnectionBad: PQconsumeInput() SSL SYSCALL error: Connection timed out
Run Code Online (Sandbox Code Playgroud)
有没有人知道这些错误的直接原因是什么?与我们的数据库连接太多了吗?我们已经通过以下方式设置了分叉:
unicorn.rb
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 30
preload_app true
before_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
Process.kill 'QUIT', Process.pid
end
defined?(ActiveRecord::Base) and
ActiveRecord::
Base.connection.disconnect!
end
after_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
end
# other setup
if defined?(ActiveRecord::Base)
config = Rails.application.config.database_configuration[Rails.env]
config['adapter'] = 'postgis'
config['pool'] = ENV['DB_POOL'] || 5
config['reaping_frequency'] = ENV['DB_REAP_FREQ'] || 10 # seconds
ActiveRecord::Base.establish_connection(config)
end
end
Run Code Online (Sandbox Code Playgroud)
和sidekiq.rb
Sidekiq.configure_server do |config|
config.redis = { :url => ENV['REDIS_URL'], :namespace => 'btsidekiq' }
if defined?(ActiveRecord::Base)
config = Rails.application.config.database_configuration[Rails.env]
config['adapter'] = 'postgis'
config['pool'] = ENV['DB_POOL'] || 5
config['reaping_frequency'] = ENV['DB_REAP_FREQ'] || 10 # seconds
ActiveRecord::Base.establish_connection(config)
end
end
Sidekiq.configure_client do |config|
config.redis = { :url => ENV['REDIS_URL'], :namespace => 'btsidekiq' }
end
Run Code Online (Sandbox Code Playgroud)
我们的数据库池大小非常大DB_POOL = 100,我们在PG数据库上,显然同时支持500个连接.
此错误是由于您的postgis适配器尝试使用 ActiveRecord 连接池中的陈旧/失效连接引起的。有两种方法可以解决这个问题:
要实现 #1,您需要设置适合 Unicorn 和 Sidekiq 的池大小,它们可能有不同的需求。
Unicorn 是单线程的,因此5每个进程的默认连接池大小对您来说是正确的。这将为每个WEB_CONCURRENCY后端独角兽工作者分配最多 5 个连接。您应该重置默认池大小并使用现有的unicorn.rb:
$> heroku config:set DB_POOL=5
Run Code Online (Sandbox Code Playgroud)
然而 Sidekiq 使用了一个非常不同的模型。默认情况下,Sidekiq 有一个进程和 N 个线程。您需要比 Sidekiq 线程数稍大的数据库池大小。您可以按如下方式在您的系统中实现这一点config/initializers/sidekiq.rb:
Sidekiq.configure_server do |config|
pool_size = Sidekiq.options[:concurrency] + 2
config.redis = { :url => ENV['REDIS_URL'], :namespace => 'btsidekiq', :size => pool_size }
if defined?(ActiveRecord::Base)
config = Rails.application.config.database_configuration[Rails.env]
config['adapter'] = 'postgis'
config['pool'] = pool_size
config['reaping_frequency'] = ENV['DB_REAP_FREQ'] || 10 # seconds
ActiveRecord::Base.establish_connection(config)
end
end
Run Code Online (Sandbox Code Playgroud)
我最好的猜测是,使用如此大的 100 个连接池,您更有可能产生死连接。适当调整池的大小应该可以解决这个问题。
如果这不起作用,您应该尝试将时间减少DB_REAP_FREQ到 5 秒。
| 归档时间: |
|
| 查看次数: |
5789 次 |
| 最近记录: |