我正在使用带有单线程Rails应用程序的Phusion Passenger的Nginx。这是捕获。在该应用程序中,我使用多线程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。
答案 0 :(得分:2)
首先,您的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启动 - 有关如何使用的更多信息,请参阅this issue on the Sidekiq repo或this helpful Heroku guide解决这个问题。
不要忘记,除了上述所有内容之外,您可以轻松地让多个服务器都运行相同的Rails应用程序,但只有一个数据库具有一个连接限制。如果您在多实例模式下运行Passenger,最多有6个进程,请将数据库池大小设置为5,然后每个Web服务器节点最多使用30个连接。如果它正在运行Sidekiq服务器,那么添加5。您可能不需要多个Sidekiq服务器,因此4个Web节点@30个连接+一个Sidekiq进程@ 5个连接= 125个最大连接,完全在您的MySQL连接限制内。
答案 1 :(得分:1)
我再次回顾了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 * passenger pool size。因此,由于乘客池大小为6,如果我的数据库池大小为1,则为6 * 1 = 6.这将是6个最大数据库连接。
Sidekiq总是以多线程模式运行。
如果有人想使用sidekiq,他们必须配置他们想要运行的线程数或使用默认值(25)。如果他们正在使用数据库(可能)然后没有遇到连接超时错误,他们将需要在其数据库池中至少具有与sidekiq线程一样多的连接。目前,他们必须在两个不同的位置配置这两个值,数据库池在database.yml中用于ActiveRecord,而sidekiq连接可以通过命令行或sidekiq yml文件。这是一个问题,因为当您修改一个需要修改它们的值时很难记住。