18

在我的 RoR4 Heroku 应用程序上配置 Puma(多线程+多核服务器)时,我需要一些帮助。Heroku 文档不是最新的。我跟着这个:配置的并发和数据库连接,它没有提到集群的配置,所以我不得不一起使用这两种类型(线程和多核)。

我目前的配置:

./过程文件

web: bundle exec puma -p $PORT -C config/puma.rb

./config/puma.rb

environment production
threads 0,16

workers 4
preload_app!

on_worker_boot do
  ActiveRecord::Base.connection_pool.disconnect!

  ActiveSupport.on_load(:active_record) do
    config = Rails.application.config.database_configuration[Rails.env]
    config['reaping_frequency'] = ENV['DB_REAP_FREQ'] || 10 # seconds
    config['pool']              = ENV['DB_POOL'] || 5
    ActiveRecord::Base.establish_connection
  end
end

问题:

a) 我是否需要像 Unicorn 中的 before_fork / after_fork 配置,因为集群工作人员是分叉的?
b) 如何根据我的应用程序调整线程数 - 将其删除的原因是什么?/ 在什么情况下会有所作为?0:16 不是已经优化了吗?
c) Heroku 数据库允许 500 个连接。根据线程、工作者和测功机计数,DB_POOL 有什么好的价值?- 每个工作人员每个测功机的每个线程在并行工作时是否需要一个单独的数据库连接?

一般来说:我的配置在并发性和性能方面应该如何?

4

2 回答 2

27

a) 我是否需要像 Unicorn 中的 before_fork / after_fork 配置,因为集群工作人员是分叉的?

通常不会,但是由于您使用preload_app的是 ,所以是的。预加载应用程序会启动并运行一个实例,然后为工作人员分配内存空间;结果是您的初始化程序只运行一次(可能分配数据库连接等)。在这种情况下,您的on_worker_boot代码是合适的。如果您不使用preload_app,则每个工作人员都会自行启动,在这种情况下,使用初始化程序将非常适合像您一样设置自定义连接。实际上,如果没有preload_app,您的on_worker_boot块会出错,因为此时 ActiveRecord 和朋友甚至都没有加载。

b) 如何根据我的应用程序调整线程数 - 将其删除的原因是什么?/ 在什么情况下会有所作为?0:16 不是已经优化了吗?

在 Heroku(和我的测试)上,你最好匹配你的min/max线程,与max<=DB_POOL设置。线程允许您的min应用程序在不负载时降低资源,这通常可以很好地释放服务器上的资源,但在 Heroku 上可能不太需要;该 dyno 已经致力于服务 Web 请求,不妨让它们准备就绪。在设置你的max线程时<=你的DB_POOL不需要环境变量,您冒着消耗池中所有数据库连接的风险,然后您有一个线程想要连接但无法获得它,您可以获得旧的“ActiveRecord::ConnectionTimeoutError - 无法在 5 秒内获得数据库连接。” 错误。不过,这取决于您的应用程序,您很可能拥有max>DB_POOL并且很好。我会说你DB_POOL应该至少与你的min线程值相同,即使你的连接没有被急切加载(如果你的应用程序从不访问数据库,5:5 线程不会打开 5 个连接)。

c) Heroku 数据库允许 500 个连接。根据线程、工作者和测功机计数,DB_POOL 有什么好的价值?- 每个工作人员每个测功机的每个线程在并行工作时是否需要一个单独的数据库连接?

生产层允许 500,很清楚:)

每个测功机每个工作人员的每个线程都可以消耗一个连接,这取决于他们是否都试图同时访问数据库。通常连接一旦完成就会被重用,但正如我在 中提到的b),如果您的线程大于您的池,您可能会遇到麻烦。连接将被重用,所有这些都由 ActiveRecord 处理,但有时并不理想。有时连接会空闲或死掉,这就是为什么建议打开 Reaper 来检测和回收死连接的原因。

于 2013-08-01T19:13:31.400 回答
3

您不希望数据库连接少于线程。请记住,每个单独的进程都有自己的连接池,因此如果您的数据库支持 20 个连接并且您想要运行 2 个进程,那么您可以在不冒超时风险的情况下运行的最多线程是 10 个线程,每个线程具有 10 个连接池。

您想为 rails 控制台会话保留一些连接。还要注意后台工作人员,以及他们是否是线程化的。

如果您的工作人员处于单独的进程 (sidekiq) 中,他们将拥有自己的池。如果您的工作线程是从 Web 进程(girl_friday 或 Sucker_punch)产生的,您将希望 DB_POOL 大于 Web 线程的最大数量,因为它们将共享一个连接池。

于 2015-08-14T21:11:56.583 回答