【问题标题】:Heroku + Sidekiq: ActiveRecord::StatementInvalid: PG::UnableToSend: SSL SYSCALL error: EOF detectedHeroku + Sidekiq:ActiveRecord::StatementInvalid:PG::UnableToSend:SSL SYSCALL 错误:检测到 EOF
【发布时间】:2013-11-17 02:36:36
【问题描述】:

您好,我们正在 Heroku 的 Cedar 堆栈上运行 Unicorn 和 Sidekiq。我们间歇性地收到以下错误

BurnThis ActiveRecord::StatementInvalid: PG::UnableToSend: SSL SYSCALL error: EOF detected

ActiveRecord::StatementInvalid: PG::ConnectionBad: PQconsumeInput() SSL SYSCALL error: Connection timed out

有没有人知道这些错误的直接原因是什么?与我们的数据库的连接太多了吗?我们已经通过以下方式设置了分叉:

独角兽.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

还有 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

我们的数据库池大小相当大 DB_POOL=100 并且我们在一个显然支持 500 个并发连接的 PG 数据库上。

【问题讨论】:

  • 只是想知道,您是否有具有“高可用性”的 Postgres 计划之一?如此处所示,addons.heroku.com/heroku-postgresql#premium-yanari
  • 我在对数据库执行重新启动数据库的操作后看到了这种类型的应用程序错误。重新启动应用程序服务器后,由于重新建立连接,错误就会消失。您是否发现看到错误与运行迁移或其他数据库活动之间有任何关联?
  • 你有什么理由在 Unicorn 配置的 after_fork 块中设置你的配置?似乎应该在这些块之外。
  • 我得到了类似的东西:ActiveRecord::StatementInvalid (PG::UnableToSend: SSL connection has been closed unexpectedly

标签: heroku connection-pooling rails-activerecord rails-postgresql heroku-postgres


【解决方案1】:

此错误是由您的 postgis 适配器尝试使用 ActiveRecord 连接池中的陈旧/死连接引起的。有两种方法可以解决这个问题:

  1. 调整连接池的大小以匹配线程/进程的数量
  2. 较低的连接回收频率(Reaper 每 N 秒检查一次池中的死连接)

要实现 #1,您需要为 Unicorn 和 Sidekiq 设置合适的池大小,它们可能有不同的需求。

Unicorn 是单线程的,因此每个进程的默认池大小5 连接对您来说是正确的。这将为每个 WEB_CONCURRENCY 后端独角兽工作者分配最多 5 个连接。您应该重置默认池大小并使用现有的unicorn.rb

$> heroku config:set DB_POOL=5

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

我最好的猜测是,使用这么大的 100 个连接池,您更有可能累积死连接。适当调整池大小应该可以解决此问题。

如果这不起作用,您应该尝试将您的 DB_REAP_FREQ 减少到 5 秒。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-15
    • 2019-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-19
    • 2012-01-19
    • 1970-01-01
    相关资源
    最近更新 更多