5

这里有点开放式问题,所以我将首先概述问题。我们有一个Resque工作人员,他应该从队列中弹出数据同步作业,原因有两个,使用 Cron(并一遍又一遍地支付 Rails 环境启动时间)很糟糕,而替代队列,以及 Github 制作当他们宣布 Resque时,这是对他们不利的一个很好的案例。此外,Redis 时间序列功能已经在我们的基础设施中发挥了重要作用,我们还将 TS 数据混洗到 RRDTool 等...

这就是问题所在,作业之间通常间隔三个小时(但员工可以随时安排作业……因此需要排队),PostgreSQL 服务器就消失了。很容易治愈,我希望reconnect: true在相应的环境下设置可以确保它按预期工作。我在几个 地方读到了一些reconnect: true不适用于使用fork(). 哪一个,Resque自然会做,开始它的工人……我不明白的部分是为什么 ActiveRecord 的重新连接在这些情况下不能工作?

我注意到 ActiveRecord 中 MySQL 适配器和 PostgreSQL 适配器的实现reconnect!不同……但无论哪种方式,我都希望 ActiveRecordreconnect: true配置能够工作。

问题似乎很清楚,当子进程存在时,它会关闭由父进程创建的文件句柄(从而挂起与数据库的连接) - 是否可以以 ActiveRecord 没有的方式关闭文件句柄认识到连接已被终止?

还有,对于它的价值,我可以在 Github 上找到一个ActiveRecord 感知 fork(),作为一个馅饼 - 它未经测试,但我认为它有效(没有在当前的 Rails 上尝试过它..)

我的问题是更多,为什么 AR 中的自动重新连接不能正常工作fork()(而且,最近 - 我不能是唯一遇到这个问题的人;我把它归结为使用 PGSQL 和 Resque!)

4

1 回答 1

7

虽然不完全是“为什么不能重新连接”的答案,但我认为可以帮助你的是以下代码放在初始化阶段的某个地方:


Resque.after_fork do |job|
  ActiveRecord::Base.connection.reconnect!
end

更新:关于重新连接 - 它似乎是 MySQL 唯一的功能。这是它在 mysql 适配器中的使用方式: https ://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapter/mysql_adapter.rb#L848 如您所见,它使用底层驱动程序的重新连接功能. https://github.com/kwatch/mysql-ruby/blob/master/ext/mysql.c#L923

另一方面,postgresql 适配器对reconnect选项没有做任何事情,您可以查看https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb

此外,PostgreSQL 网站明确表示“使用开放的 libpq 连接分叉一个进程会导致不可预知的结果” - http://www.postgresql.org/docs/9.0/interactive/libpq-connect.html 而且很明显C 驱动程序不提供任何重新连接功能。

于 2011-04-17T22:55:46.630 回答