Heroku上的Puma Cluster配置

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

我目前的配置:

./Procfile

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

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

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 threads值相同,即使你的连接没有被急切加载(如果你的应用程序永远不会访问数据库,5:5线程也不会打开5个连接)。

c)Heroku数据库允许500个连接。 根据线程,工作线程和动态计数,DB_POOL的值是多少? – 并行工作时,每个dyno的每个工作线程的每个线程是否都需要唯一的DB连接?

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

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

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

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

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