【问题标题】:Resque worker causing ActiveRecord::StatementInvalid: PG::Error: SSL SYSCALL error: EOF detectedResque worker 导致 ActiveRecord::StatementInvalid: PG::Error: SSL SYSCALL error: EOF detected
【发布时间】:2012-12-16 08:51:13
【问题描述】:

我现在在两个应用程序上都遇到了这个问题。 Heroku 自己(还)无法提供太多帮助。

我正在使用:

  • Rails 3.2.9
  • Unicorn
  • Heroku,带有 Postgres Dev(免费)数据库和 OpenRedis Micro
  • MongoDB(用于存储社交网络状态)
  • Resque
  • Resque-scheduler

在我的本地 Postgres 和 Redis 数据库上运行时一切正常。

以下是我的 Heroku 日志中的错误示例:

2013-01-01T21:17:27+00:00 app[resque_worker.1]: Found job on #<Resque::Queue:0x00000006652920>
2013-01-01T21:17:27+00:00 app[resque_worker.1]: got: (Job{facebook} | FacebookRefresh | ["facebook_key"])
2013-01-01T21:17:27+00:00 app[resque_worker.1]: Running before_fork hooks with [(Job{facebook} | FacebookRefresh | ["facebook_key"])]
2013-01-01T21:17:27+00:00 app[resque_worker.1]: Running after_fork hooks with [(Job{facebook} | FacebookRefresh | ["facebook_key"])]
2013-01-01T21:17:27+00:00 app[resque_worker.1]: resque-2.0.0.pre.1: Processing facebook since 1357075047
2013-01-01T21:17:27+00:00 app[resque_worker.1]: resque-2.0.0.pre.1: Forked 503 at 1357075047
2013-01-01T21:17:27+00:00 app[resque_worker.1]: Running before_perform hooks with [(Job{facebook} | FacebookRefresh | ["facebook_key"])]
2013-01-01T21:17:27+00:00 app[resque_worker.1]: :             SELECT a.attname, format_type(a.atttypid, a.atttypmod),
2013-01-01T21:17:27+00:00 app[resque_worker.1]:               FROM pg_attribute a LEFT JOIN pg_attrdef d
2013-01-01T21:17:27+00:00 app[resque_worker.1]:                 ON a.attrelid = d.adrelid AND a.attnum = d.adnum
2013-01-01T21:17:27+00:00 app[resque_worker.1]:                      pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
2013-01-01T21:17:27+00:00 app[resque_worker.1]: ). Retrying...
2013-01-01T21:17:27+00:00 app[resque_worker.1]: Performing FacebookRefresh caused an exception (PG::Error: SSL SYSCALL error: EOF detected
2013-01-01T21:17:27+00:00 app[resque_worker.1]:              WHERE a.attrelid = '"facebook_accounts"'::regclass
2013-01-01T21:17:27+00:00 app[resque_worker.1]:              ORDER BY a.attnum
2013-01-01T21:17:27
+00:00 app[resque_worker.1]:                AND a.attnum > 0 AND NOT a.attisdropped
2013-01-01T21:17:27+00:00 app[resque_worker.1]: :             SELECT a.attname, format_type(a.atttypid, a.atttypmod),
2013-01-01T21:17:27+00:00 app[resque_worker.1]:               FROM pg_attribute a LEFT JOIN pg_attrdef d
2013-01-01T21:17:27+00:00 app[resque_worker.1]:                 ON a.attrelid = d.adrelid AND a.attnum = d.adnum
2013-01-01T21:17:27+00:00 app[resque_worker.1]: (Job{facebook} | FacebookRefresh | ["facebook_key"]) failed: #<ActiveRecord::StatementInvalid: PG::Error: SSL SYSCALL error: EOF detected
2013-01-01T21:17:27+00:00 app[resque_worker.1]: >
2013-01-01T21:17:27+00:00 app[resque_worker.1]:                      pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
2013-01-01T21:17:27+00:00 app[resque_worker.1]:                AND a.attnum > 0 AND NOT a.attisdropped
2013-01-01T21:17:27+00:00 app[resque_worker.1]:              WHERE a.attrelid = '"facebook_accounts"'::regclass
2013-01-01T21:17:27+00:00 app[resque_worker.1]:              ORDER BY a.attnum
2013-01-01T21:17:27+00:00 app[resque_worker.1]: Running before_fork hooks with [(Job{facebook} | FacebookRefresh | ["facebook_key"])]

我在我的独角兽的配置文件中尝试了很多 before_hook 和 after_hook 的东西,但它们似乎都没有帮助。

# What the timeout for killing busy workers is, in seconds
timeout 60

# Whether the app should be pre-loaded
preload_app true

# How many worker processes
worker_processes 3

before_fork do |server, worker|
  # Replace with MongoDB or whatever
  if defined?(ActiveRecord::Base)
    ActiveRecord::Base.connection.disconnect!
    Rails.logger.info('Disconnected from ActiveRecord')
  end

  # If you are using Redis but not Resque, change this
  if defined?(Resque)
    Resque.redis.quit
    Rails.logger.info('Disconnected from Redis')
  end

  sleep 1
end

after_fork do |server, worker|
  if defined?(ActiveRecord::Base)
    ActiveRecord::Base.establish_connection
    Rails.logger.info('Connected to ActiveRecord')
  end

  if defined?(Resque)
    Resque.redis = ENV['OPENREDIS_URL'] || 'redis://localhost:6379'
    Rails.logger.info('Connected to Redis')
  end
end

还有我的 Procfile

web: bundle exec unicorn -c lib/unicorn/config.rb -p $PORT
resque_scheduler: env bundle exec rake resque:scheduler
resque_worker: env QUEUE=* bundle exec rake environment resque:work

所以我想知道的一件事是我的 resque_worker 根本不使用 Unicorn 配置,而且由于它运行在一个完全独立的 Heroku worker 上,我不确定它是否有任何方法会知道这些东西。 Web 实例和调度程序都很好。它只是 resque_worker 在每次 postgres 调用时都会爆炸。

我并没有从工作人员那里进行任何特别疯狂的数据库调用。一个例子可能是:

def queue_users_for_refresh
  FacebookAccount.all.each do |x|
    Resque.enqueue(FacebookAccountRefresh, x.username)
  end
end

稍后(在 FacebookAccountRefresh 中)另一个是:

FacebookAccount.where(:username => user).first

【问题讨论】:

  • @tibbion resque 与 Unicorn 有什么关系 ASFAIK resque run vai rake task 它会有自己的环境

标签: ruby-on-rails heroku resque unicorn


【解决方案1】:

这看起来像是由于不正确地跨进程共享数据库连接而导致的错误。当 Resque 工作线程在分叉后没有重新初始化数据库连接时,就会发生这种情况。

你有 Resque 初始化器吗?您似乎缺少用于 Resque 工作人员的 after_fork 指令,以匹配您的 Unicorn 应用服务器工作人员中的指令。

添加/编辑您的 Resque 初始化程序文件(即:config/initializers/resque.rb):

Resque.after_fork = Proc.new { ActiveRecord::Base.establish_connection }

【讨论】:

  • monogid 或 mongodb 是否有替代方法。
猜你喜欢
  • 2012-01-19
  • 1970-01-01
  • 1970-01-01
  • 2021-04-10
  • 1970-01-01
  • 1970-01-01
  • 2012-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多