【问题标题】:Slow and frequent PostgreSQL database connection booting in Rails APIRails API 中缓慢而频繁的 PostgreSQL 数据库连接启动
【发布时间】:2020-07-11 18:50:40
【问题描述】:

我有一个带有 PostgreSQL 数据库的 Rails API。

对 API 的一些请求显示出一种奇怪的行为,即 不依赖于端点。

这些请求(约占总请求的 5-10%)以 相同的 7 个数据库查询:

  • 将 client_min_messages 设置为?
  • SET standard_conforming_strings = on
  • 将 SESSION 时区设置为 ?
  • SELECT t.oid, t.typname FROM pg_type WHERE t.typname IN (?) ...

在执行 7 个查询之前,请求也需要很长时间才能启动。

似乎是数据库适配器启动了连接。 ActiveRecord::ConnectionAdapters::PostgreSQLAdapter

这会显着减慢查询速度。

我正在使用带有默认参数的 PostegreSQL 11.6 AWS RDS 实例。

这是我的 database.yml 配置:

default: &default
  adapter: postgresql
  encoding: unicode
  username: *****
  password: *****
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

production:
  <<: *default
  database: *****
  username: *****
  password: *****
  pool: 50

如何减少发起连接的数量? 有没有办法缓存查询?

谢谢,

【问题讨论】:

  • 你需要什么信息?
  • 在pg_stat_activity中,一般有多少'client backend'连接是打开的,它们打开了多长时间(backend_start)。另外,当你说他们需要很长时间才能开始时,你指的是多长时间? 5 毫秒? 5 秒?
  • 大约有 3 个连接打开,我会说它们通常平均持续 15 分钟。启动大约需要 50-100ms,而正常请求在 10ms 左右。
  • 问题连接是否也仅每 15 分钟出现一次,还是比这更频繁?

标签: ruby-on-rails postgresql amazon-rds


【解决方案1】:

遇到了同样的事情,这就是我认为正在发生的事情:

每次实例化新连接时,它都会执行您上面提到的引导查询。假设未产生新进程,则需要实例化新连接,因为 ActiveRecord 已获取现有连接。

默认情况下,ConnectionPool::Reaper 将断开任何空闲超过 5 分钟的连接。 见:https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/ConnectionPool.html

如果您的 API 在 5 分钟内未收到任何请求并且所有连接都已获得,则下一个请求将需要实例化新连接并因此运行查询。

如何减少发起连接的数量?

您可以在database.yml 中设置idle_timeout0。这会阻止 ActiveRecord 获取连接,但可能会导致问题,具体取决于正在运行的进程数量以及您的 PG max_connections 值是什么。

有没有办法缓存查询?

有一个已解决的问题讨论了这个问题,但今天似乎无法缓存这些内容。 https://github.com/rails/rails/issues/35311

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-07
    • 2012-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-24
    • 2015-11-06
    相关资源
    最近更新 更多