简体   繁体   English

Rails 数据库连接池水合

[英]Rails DB Connection Pool Hydration

I'm working on a Rails 7 app with some pretty tight response time SLAs.我正在开发一个响应时间 SLA 非常严格的 Rails 7 应用程序。 I am well within SLA during normal runtime.在正常运行时,我完全符合 SLA。 Where I fall painfully short is first request.我痛苦地缺乏的地方是第一个请求。 I've added an initializer that will load up ActiveRecord and make sure all of my DB models are loaded.我添加了一个初始化程序,它将加载 ActiveRecord 并确保我的所有数据库模型都已加载。 It hydrates some various memory caches, etc. This took me pretty far.它滋润了一些各种 memory 缓存等。这让我走了很远。 My first response time was reduced about 60%.我的第一次响应时间减少了大约 60%。 However, I've been trying to figure out a couple things are are still slowing down first response time.但是,我一直在试图弄清楚有几件事仍在减慢第一响应时间。

  1. First API request does a check to see if I need to do a rails migration.第一个 API 请求会检查我是否需要进行 Rails 迁移。 I've not figured out how to move this check to init.我还没有想出如何将此检查移动到 init。
  2. First API request appears to be be using a fresh DB Pool.. not the one that was used in init phase.第一个 API 请求似乎正在使用新的数据库池……而不是在初始阶段使用的那个。 I've tried fully hydrating the pool to spare the API from creating them when Rails kicks on, but I've not figured it out.我已经尝试完全补水池以防止 API 在 Rails 启动时创建它们,但我还没有弄清楚。

In an initializer I can do something like this:在初始化程序中,我可以这样做:

connections = []
ActiveRecord::Base.connection.pool.size.times do
  connections << ActiveRecord::Base.connection.pool.checkout
end

connections.each { ActiveRecord::Base.connection.pool.checkin(_1) }

According to my PG logs, this opens up the connections and Rails does all of this typing queries, setting session properties, etc. However, when I go to fire off my first API call, my pool is empty.根据我的 PG 日志,这会打开连接,Rails 会执行所有这些键入查询,设置 session 属性等。但是,当我 go 触发我的第一个 API 调用时,我的池是空的。

In the end what ended up being the general issue was I needed to be hydrating the pool with the correct connections.最后,最终成为普遍问题的是我需要通过正确的连接为泳池补水。 on_worker_boot is because this is running behind puma. on_worker_boot是因为这是在 puma 后面运行的。

on_worker_boot do
  ActiveRecord::Base.connected_to(role: :reading) do
    # spin up db connections
    connections = []
    (ActiveRecord::Base.connection.pool.size - 1).times do
      connections << ActiveRecord::Base.connection.pool.checkout
    end

    connections.each { |x| ActiveRecord::Base.connection.pool.checkin(x) }
  end
end

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

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