我在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连接?
一般情况:我的配置应该如何兼顾并发和性能?
答案 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线程数,因为它们将共享一个连接池。