Heroku上的Puma Cluster配置

时间:2013-07-28 00:03:14

标签: ruby-on-rails postgresql heroku unicorn puma

我在RoR4 Heroku应用程序上配置Puma(多线程+多核服务器)需要一些帮助。 Heroku上的文档并不是最新的。我跟着这个:Concurrency and Database Connections进行配置,没有提到Cluster的配置,所以我不得不同时使用这两种类型(线程和多核)。

我目前的配置:

./ Procfile

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

./配置/ 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的值是多少? - 并行工作时,每个dyno的每个工作线程的每个线程是否都需要唯一的DB连接?

一般情况:我的配置应该如何兼顾并发和性能?

2 个答案:

答案 0 :(得分:27)

  

a)我是否需要像之前的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的值取决于线程,worker和dyno计数? - 是吗   每个dyno每个工作线程的每个线程都需要一个唯一的DB连接   并行工作?

Production Tier允许500,清楚:)

每个dyno 的每个工作线程的每个线程都可以使用连接,具体取决于它们是否都在尝试同时访问数据库。通常连接会在完成后重复使用,但正如我在b)中提到的那样,如果您的线程大于您的池,则可能会遇到错误的时间。连接将被重用,所有这些都由ActiveRecord处理,但有时不理想。有时连接会闲置或死亡,这就是建议启用Reaper以检测和回收死连接的原因。

答案 1 :(得分:3)

您不需要比线程更少的数据库连接。请记住,每个单独的进程都有自己的连接池,因此如果您的数据库支持20个连接,并且您希望运行2个进程,则可以运行而不会有超时风险的大多数线程是10个线程,每个线程具有10个连接池。

您想为rails控制台会话留下一些连接。还要注意后台工作者,以及他们是否有线程。

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