Rails、Puma、Sidekiq 如何计算总数据库连接数?

Apa*_*ith 5 database ruby-on-rails amazon-web-services puma ruby-on-rails-5

ActiveRecord::ConnectionTimeoutError一天收到一两次。有人可以帮我计算我的应用程序与我的数据库建立了多少连接吗?并建议优化我的连接?

这是我的配置

自动售货机

Database : Mysql   
Version  : 5.7.23   
Provider : AWS RDS (db.m5.large, vCPU: 2, RAM: 8GB)
Run Code Online (Sandbox Code Playgroud)

3台采用波纹管配置的服务器

# database.yml
  pool: 20

# puma.rb 
  RAILS_MAX_THREADS : 5
  WEB_CONCURRENCY   : 2
Run Code Online (Sandbox Code Playgroud)

1 个带有波纹管配置的 sidekiq 服务器

# sidekiq 
  concurrency:  25
Run Code Online (Sandbox Code Playgroud)

我试图获得我的数据库能够处理的最大连接数

# MySQL Max connections ("show global variables like 'max_connections';")
  624
Run Code Online (Sandbox Code Playgroud)

R. *_*rra 5

数据库连接总数等于每台服务器的连接数乘以服务器数。

数据库连接总数 = 每台服务器的连接数 * 服务器数量。

每台服务器的连接数 = AR 数据库池大小 * 每台服务器的进程数(通常使用 WEB_CONCURRENCY 或 SIDEKIQ_COUNT 设置)

因此,对于 Web 服务器,您拥有:

AR 数据库池大小 = 20

每台服务器的进程 = 2

服务器数量 = 3

数据库连接总数(Web 服务器)= 20 * 2 * 3 = 120

sidekiq 服务器的:

AR 数据库池大小 = 20

每台服务器的进程 = 1

服务器数量 = 1

数据库连接总数(Sidekiq 服务器)= 20 * 1 * 1 = 20

因此,预期的数据库连接总数应该为140,这远低于 RDS 实例的限制。

我的猜测是,您得到的是ActiveRecord::ConnectionTimeoutError因为您的 Sidekiq 并发设置高于 AR 连接池值。所有 Sidekiq 线程都需要 ActiveRecord 数据库连接,因此将 AR 池大小设置为小于Sidekiq 并发数的数字意味着某些 Sidekiq 线程将被阻塞,等待空闲的数据库连接。在您的情况下,在某个时间点,您可能有 25 个线程尝试通过最多可使用 20 个连接的数据库池访问数据库,如果线程在 5 秒内无法获得空闲数据库连接,您将获得一个连接超时错误。

在 Sidekiq 中,数据库连接总数应该是

最小值(需要数据库连接的线程数、AR 数据库池大小) * 每台服务器的进程数(WEB_CONCURRENCY 或 SIDEKIQ_COUNT) * 服务器计数。

此外,Sidekiq文档指出

从 Rails 5 开始,RAILS_MAX_THREADS 可用于配置 Rails 和 Sidekiq 并发性。请注意,ActiveRecord 有一个连接池,需要在 config/database.yml 中正确配置它才能在高并发情况下正常工作。设置池等于线程数pool: <%= ENV['RAILS_MAX_THREADS'] || 10 %>

此答案的大部分内容基于Nate Berkopec的Sidekiq 实践电子邮件系列