[英]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.