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

问题描述 投票:3回答:1

我每天要获得ActiveRecord::ConnectionTimeoutError一次或两次。有人可以帮助我计算应用程序与数据库的连接数吗?和建议来优化我的联系?

这是我的配置

AWS

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

具有波纹管配置的3台服务器

# database.yml
  pool: 20

# puma.rb 
  RAILS_MAX_THREADS : 5
  WEB_CONCURRENCY   : 2

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

# sidekiq 
  concurrency:  25

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

# MySQL Max connections ("show global variables like 'max_connections';")
  624
ruby-on-rails database amazon-web-services ruby-on-rails-5 puma
1个回答
0
投票

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

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

[每台服务器的连接数= 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 documentation指出

[从Rails 5开始,RAILS_MAX_THREADS可用于配置Rails和Sidekiq并发。请注意,ActiveRecord具有一个连接池,需要在config / database.yml中对其进行正确配置,以便在大量并发情况下正常工作。将池设置为等于线程数pool: <%= ENV['RAILS_MAX_THREADS'] || 10 %>

此答案大部分基于[Nate Berkopec中的Sidekiq in Practice电子邮件系列”>

© www.soinside.com 2019 - 2024. All rights reserved.