【问题标题】:Puma Cluster configuration on HerokuHeroku 上的 Puma 集群配置
【发布时间】:2013-07-28 01:00:22
【问题描述】:

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

我目前的配置:

./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 有什么好的价值? - 在并行工作时,每个工作人员每个测功机的每个线程是否都需要一个单独的数据库连接?

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

【问题讨论】:

  • 在调整线程数方面。我读了一篇关于 Unicorn worker 调优的教程,该教程建议运行 ab 并增加 worker 数量(在你的情况下是线程),直到性能下降(请求需要更多时间才能完成)。最好使用一个相当动态的页面,并首先查看不同的请求/并发比例如何起作用(还要记住,如果您执行许多请求,heroku 可能会阻止您怀疑 DoS)
  • @MichaelSzyndel 所以我基本上必须先检查每个工人,检查性能,然后通过线程并再次检查?这不取决于具体要求什么吗?
  • 从我在某处读到的内容,Heroku 每个测功机有两个核心(4 个虚拟)。每个测功机有一个进程是最佳的,然后由您决定每个进程运行多少个线程。我会用 ab 测试。还要记住,如果您超过 521MB 的 RAM,Heroku 将发送警报,并且它会以 >1GB 的速度交换(与 heroku 文档确认)
  • 您使用哪种测功机类型?您提到:Multi-Thread+Multi-Core Server 是否意味着 PX dyno(每月 500 美元)?

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


【解决方案1】:

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 的值取决于线程、工作者和测功机计数? - 做 每个工作人员每个测功机的每个线程都需要一个单独的数据库连接 并行工作?

Production Tier 允许 500,要清楚:)

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

【讨论】:

  • workers 2 表示 puma 的额外工作进程,我说得对吗?所以,总共有 3 进程?
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 2016-06-20
    • 2020-01-05
    • 1970-01-01
    • 2014-11-19
    • 2017-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    相关资源
    最近更新 更多