gpt4 book ai didi

ruby-on-rails - Sidekiq,线程用完 - Rails 离开并且没有收获 connection_pool 线程

转载 作者:太空宇宙 更新时间:2023-11-03 16:13:02 24 4
gpt4 key购买 nike

我们有一个在以下配置中运行的生产系统:

Ruby 2.5.1
Rails 5.2.2
Sidekiq 5.2.5
Sidekiq-cron 1.1.0
Redis 4.1.0
  adapter: postgresql
pool: 10
reaping_frequency: 10
timeout: 5000
username: ...
password: ...
host: ...

它有 3 个队列(默认/高/中优先级),每个队列有 4 个线程。我们最近添加了一个新的 sidekiq cron 作业,它在高队列中每 30 分钟运行一次,几天后系统就会陷入僵局,无法为连接池生成更多线程。我们已经追踪到“高”队列和这个新作业,上次它挂断了这个“高”队列有 1900 个线程,几乎所有线程看起来都是“连接池”。 kill -9 在队列的进程上,我们的主管重新启动它,一切都很好,持续了 5-7 天,然后又停止了。

这个新作业在远程数据库中创建了许多新列表,我们有用于本地记录的本地 ActiveRecord 模型和父类(super class) RemoteList 模型。我们使用 RemoteModel.establish_connection...。事务打开,写入,写入...,关闭事务,关闭连接。我们与大量远程数据库进行交流,因此该模型非常适合我们。

新工作人员反复调用已使用 3 年以上且未发出锁定的列表发布者。我们可以看到,每次我们通过旧列表发布者写入远程数据库时,都会添加一个新的连接池进程。

我试过:

  1. 手动从池中获取连接并返回,对于 ActiveRecord 本身和我们的父类(super class),一个,两个,一个都没有。
  2. 将 block 包装在 ActiveRecord::Base.connection_pool.with_connection

以上都没有任何影响,线程数只是随着我们拆分的每个文件不断增长,直到我们达到死锁并且没有更多线程。收割似乎根本没有做任何事情。这个 worker 唯一不同的是它调用 open3.capture3 到一个“C”程序来做一些文件分割,比我们在 ruby​​ 中做的要快得多,但我可以看到生成的 shell已经关闭并完成,但我们仍然得到这些“连接池”线程。

那里的任何人都有任何好主意。

谢谢凯特

列表发布

CoreDBListModel.semaphore.synchronize do
begin

.... setup removed....
CoreDBListModel.establish_connection(@config['database'])

CoreDBListModel.transaction do
core = CoreDBListModel.where(:description => list.list_id).first
core.pending = true
core.name = list.name
core.tags = category.name
core.pcount = list.count
core.active = list.deleted ? 2:0
core.save

... make list insert data.....
mass_insert = "INSERT INTO #{mapping['table']} (data_id, data, fulldata) VALUES #{inserts.join(", ")}"
CoreDBListModel.connection.execute(mass_insert)

# Mark as completed
core.pending = false
core.save

end

rescue => e
@code = 500
@message = "Failed - #{e.message}, #{e.backtrace[0]}"
Rails.logger.error("CoreDBList() - Publishing failed - #{list.list_id}")
Rails.logger.error("CoreDBList() - Publishing failed - #{e.message}")
Rails.logger.error("CoreDBList() - Publishing failed - #{e.backtrace.first(10).join("\n")}")
ensure
begin
# Close our DB connection
CoreDBListModel.connection.close
rescue
end
end
end

在下面添加了一个包含更多详细信息的答案,但基本上问题似乎出在 5.1.6 和 5.2.1 之间的 Rails 上。如果我们回滚到 5.1.6,问题就会消失。

https://github.com/rails/rails/issues/36333

最佳答案

首先确定线程泄漏的速率——它是在每次任务运行时发生还是偶尔发生?如果是前者 - 你很幸运,可以尝试通过记录 ObjectSpace.each_object(Thread).count 进行调试(注意,这是一个繁重的功能,可能不适合生产中的高负载)在你的几个点尝试检测线程泄漏位置的代码。

怀疑是 Open3.capture3 - 如果您不在 C 代码中使用单独的 stderr,它会启动两个线程用于读取进程的 stdin/stdout 和一个用于读取进程退出状态的线程 -我建议切换到 capture2 并查看线程泄漏是否慢了大约 1/3 倍。我记得 popen3 和子进程有问题,不使用 stderr 或打开/关闭 std 流的某种组合或不读取 stdin,现在记不起细节。

关于ruby-on-rails - Sidekiq,线程用完 - Rails 离开并且没有收获 connection_pool 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56242038/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com