【问题标题】:ActiveRecord unable to reconnect when running inside forked/threaded application?在分叉/线程应用程序中运行时,ActiveRecord 无法重新连接?
【发布时间】:2023-03-27 10:29:01
【问题描述】:

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

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

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

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

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

p>

我的问题更多,如果你 fork(),为什么 AR 中的自动重新连接不能工作?(而且,最近 - 我不能是唯一遇到这个问题的人;我将其归结为将 PGSQL 与 Resque 一起使用!)

【问题讨论】:

    标签: mysql ruby postgresql activerecord resque


    【解决方案1】:

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

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

    更新: 关于重新连接 - 它似乎是 MySQL 唯一的功能。 这是它在 mysql 适配器中的使用方式: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/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 驱动程序不提供任何重新连接功能。

    【讨论】:

    • Roman,当然 - 我有解决方法,但我专门寻找 reconnect: true 不起作用的原因。我想知道这是否与并发有关(activerecord 的 allowconcurrency 标志) - 并认识到第一个连接仍处于连接状态……但我真的很茫然。
    • 好吧,通过查看 activerecord 代码,我可以看出,PostgreSQL 适配器不支持 reconnect 选项。
    • Roman,你能说得更具体点吗,也许是一个链接——我在某个地方找到了一个实现……(我确定)
    • 罗曼,几乎不是我想要的(好消息!),但值得 +50 代表,因为写得好,有用的答案,奖励!
    • postgres 适配器确实有reconnect feature,但即使没有,您也可以断开连接并重新连接。断开连接和重新连接很重要的原因是因为在 Resque 分叉之后,每个分叉都有一个完全相同的连接的副本;如果他们尝试同时使用它,数据将进入随机(分叉)进程。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-09
    • 2022-01-13
    • 1970-01-01
    • 2013-08-07
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多