[英]Ensure max database connections is not exceeded with Rails and Sidekiq
我正在使用带有单线程Rails应用程序的Nginx和Phusion Passenger。 这是捕获。 在该应用程序中,我使用多线程sidekiq来执行一些后台作业。 通常在我的database.yml中,我只需要将池值设置为1.这是一个例子:
default: &default
adapter: mysql2
encoding: utf8
collation: utf8_unicode_ci
pool: 1
username: username
password: password
host: localhost
原因是因为每个tcp套接字连接打开,当http请求通过该套接字进入时,nginx将接收请求并将信息传递给乘客。 Passenger检测到它的Rails应用程序,它产生一个Rails实例,它将响应转换为html,然后发送回nginx,然后传回给客户端(浏览器)。因此对于每个乘客实例,我只需要一个数据库连接,使用单线程Rails应用程序。
但是在我的sidekiq.yml中,我将并发设置为5:
:concurrency: 5
这意味着对于每个乘客机架实例,我将有由sidekiq处理的5个并发线程加上主应用程序的一个连接,即一个乘客实例的总共6个数据库连接。
当我查看乘客状态时,我注意到max_pool_size设置为6:
----------- General information -----------
Max pool size : 6
那么这是否意味着乘客不会同时产生超过6个Rails实例? 如果是这样的话,这是否意味着我的数学是正确的:6(实例)* 6(数据库连接:5为sidekiq,1为主app)= 36(我的rails应用程序可以同时处理的总数据库连接)。
现在我的mysql数据库配置为处理151个最大并发连接。
SHOW VARIABLES LIKE "max_connections";
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 151 |
+-----------------+-------+
我只是想确保我的数学是正确的乘客,铁路和sidekiq。
首先,您的Sidekiq流程和您的Web服务器(在您的情况下,Passenger)是分开的。 Passenger的线程池大小对您的Sidekiq并发性没有影响; 相反,您的Sidekiq配置指定单独的并发。 所以,我们将分别考虑这两个:
ActiveRecord数据库池值是Web进程将在所有线程中使用的数据库连接数。 如果您的Passenger服务器设置为多进程模式,则Web进程的最大连接数为db pool size * passenger pool size
。 另一方面,如果你在多线程模式下设置它(我建议如果可能),你的最大连接只是db pool size
(乘以许多进程正在运行;例如,Puma默认运行)两个进程最多包含15个线程,因此在这种情况下最大连接数为30)。
因此,如果您使用的是多线程模式,则池大小为1
是绝对不够的 - 您至少需要与预期的线程一样大的池。 在多进程模式中, 1
可能有效,但我怀疑它是否真的值得从默认值5
消失,直到遇到问题。
Sidekiq总是以多线程模式运行(你可以在技术上运行多个进程,但我认为你不是)。 因此,如上所述,您希望连接池至少与线程数一样大。 这可能意味着您在技术上需要两个不同的db池值值,具体取决于Rails env是为Passenger启动还是为Sidekiq启动 - 请参阅Sidekiq repo上的此问题或此有用的Heroku指南 ,了解有关如何使用的更多信息解决这个问题
不要忘记,除了上述所有内容之外,您可以轻松地让多个服务器都运行相同的Rails应用程序,但只有一个数据库具有一个连接限制。 如果您在多实例模式下运行Passenger,最多有6个进程,请将数据库池大小设置为5,然后每个Web服务器节点最多使用30个连接。 如果它正在运行Sidekiq服务器,那么添加5。 您可能不需要多个Sidekiq服务器,因此4个Web节点@30个连接+一个Sidekiq进程@ 5个连接= 125个最大连接,完全在您的MySQL连接限制内。
我再次回顾了Passenger文档,虽然上面的答案回答了这个问题,但我想补充一点细节:
Watchdog监控Passenger Core和UstRouter。 如果它们中的任何一个崩溃,它们将由Watchdog重新启动。
passenger-memory-stats将验证上述三个进程以及衍生的机架应用程序:
------ Passenger processes ------ PID VMSize Private Name --------------------------------- 18355 419.1 MB ? Passenger watchdog 18358 1096.5 MB ? Passenger core 18363 427.2 MB ? Passenger ust-router 18700 818.9 MB 256.2 MB Passenger RubyApp: myapp_rack_rails 24783 686.9 MB 180.2 MB Passenger RubyApp: myapp_rack_rails
乘客状态显示max_pool_size为6.也就是说,乘客核心最多会产生6个机架应用程序:
----------- General information -----------
Max pool size : 6
App groups : 2
Processes : 3
如另一个答案所述,ActiveRecord数据库池值是Web进程将在所有线程中使用的数据库连接数。
但由于我使用的是在多进程模式下设置的免费Passenger服务器,因此我的Web进程的最大连接数是db pool size *乘客池大小。 因此,由于乘客池大小为6,如果我的数据库池大小为1,则为6 * 1 = 6.这将是6个最大数据库连接。
Sidekiq始终以多线程模式运行。
如果有人想使用sidekiq,他们必须配置他们想要运行的线程数或使用默认值(25)。 如果他们正在使用数据库(可能)然后没有遇到连接超时错误,他们将需要在其数据库池中至少具有与sidekiq线程一样多的连接。 目前,他们必须在两个不同的位置配置这两个值,数据库池在database.yml中用于ActiveRecord,而sidekiq连接可以通过命令行或sidekiq yml文件。 这是一个问题,因为当您修改需要修改两个值的一个值时很难记住。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.