繁体   English   中英

关闭 Rails ActiveRecord 连接池

[英]Close Rails ActiveRecord Connection Pool

我正在使用第二个数据库,其中包含我的 API 中的数据集。

每个 API 请求在该数据库上最多可以有 3 个查询,因此我将它们分成三个线程。 为了保证线程安全,我使用了一个连接池。

但是在整个代码运行之后,ConnectionPool 线程并没有终止。 所以基本上每次发出请求,我们都会在服务器上有一个新的Thread,直到基本上没有memory了。

有没有办法关闭连接池线程? 或者我在为每个请求创建连接池时做错了吗?

我这样设置连接池:

begin
  full_db = YAML::load(ERB.new(File.read(Rails.root.join("config","full_datasets_database.yml"))).result)
  resolver = ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver.new(full_db)
  spec = resolver.spec(Rails.env.to_sym)
  pool = ActiveRecord::ConnectionAdapters::ConnectionPool.new(spec)

然后我遍历查询数组并将结果获取到查询

returned_responses = []
queries_array.each do |query|
  threads << Thread.new do
    pool.with_connection do |conn|
     returned_responses << conn.execute(query).to_a
    end
  end
end

threads.map(&:join)

returned_responses

最后我关闭了连接池中的连接:

ensure
 pool.disconnect!
end

按照 Rails 中处理多个数据库的官方方式:

https://guides.rubyonrails.org/active_record_multiple_databases.html

我无法给你一个准确的答案,因为我没有你的源代码来完全理解整个上下文。 如果我上面发送的设置不适用于您的用例,您可能错过了一些后台清理任务。 你可以参考这个文档:

https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/ConnectionPool.html

由于您想直接进行 SQL 查询而不利用 ActiveRecord 作为 ORM,但您确实想利用 ActiveRecord 连接池,我建议您创建一个新的抽象 class,如ApplicationRecord

# app/models/full_datasets.rb

class FullDatasets < ActiveRecord::Base
  self.abstract_class = true

  connects_to database: {
    writing: :full_datasets_database,
    reading: :full_datasets_database
  }
end

您需要在database.yml配置数据库full_datasets_database ,以便connects_to能够连接到它。

然后,您将能够直接连接到该数据库,并通过引用 class 而不是ActiveRecord::Base对其进行直接 SQL 查询:

FullDatasets.connection.execute(query)

连接池将透明地发生在不同的池中:

FullDatasets.connection_pool.object_id
=> 22620

ActiveRecord::Base.connection_pool.object_id
=> 9000

您可能需要进行额外的配置,例如将模式转储到db/full_datasets_schema.rb ,但您必须执行的任何其他故障排除或配置将在https://guides.rubyonrails.org/active_record_multiple_databases.html中进行描述。

这个解释的简短版本是,您应该尝试尽可能多地利用 ActiveRecord,以便您的实现干净直接,同时仍然允许您直接下降到原始 SQL。

花了一些时间后,我终于找到了答案。 一般的想法来自@anothermg ,但我必须做一些更改才能在我的 rails (5.2) 版本中工作。

我在config/full_datasets_database.yml中设置了数据库我已经有了以下初始化程序:

#! config/initializers/db_full_datasets.rb
DB_FULL_DATASETS = YAML::load(ERB.new(File.read(Rails.root.join("config","full_datasets_database.yml"))).result)[Rails.env]

我创建了以下 model 来创建到新数据库的连接:

#! app/models/full_datasets.rb
class FullDatasets < ActiveRecord::Base
  self.abstract_class = true

  establish_connection DB_FULL_DATASETS
end

在实际模块上,我添加了以下代码:

  def parallel_queries(queries_array)
    returned_responses = []
    threads = []

    conn = FullDatasets.connection_pool

    queries_array.each do |query|
      threads << Thread.new do
        returned_responses << conn.with_connection { |c| c.execute(query).to_a }
      end
    end

    threads.map(&:join)

    returned_responses
  end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM