RAILS_MAX_THREADS 是 Puma 将在构建期间设置和缩放的东西,还是我应该设置它?

Is RAILS_MAX_THREADS something that Puma will set and scale during build time , or should I set it?

我知道 Rails 5 随 Puma(我们正在使用)一起提供,并将寻找 RAILS_MAX_THREADS 作为环境变量或默认为 5 个线程,但我收到超时错误默认值。我查看了我的数据库,发现它的最大连接数是几千。

这可能很愚蠢,但这是 Puma 会根据其设置自动设置和扩展的东西,还是我需要在环境变量中明确设置它?如果需要手动设置,RAILS_MAX_THREADS 的值是多少?

我发现以下内容很有帮助,但我没有完全掌握可伸缩性部分:

https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server https://devcenter.heroku.com/articles/concurrency-and-database-connections

Puma其实有两个参数,线程数和worker数。如果我们稍微改变一下默认值 puma.rb,它看起来像这样:

# WORKERS_NUM is not a default env variable name
workers Integer(ENV['WORKERS_NUM'] || 1)
max_threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 1)
min_threads_count = max_threads_count
threads min_threads_count, max_threads_count

工人数量是 Puma 为您生成的独立进程的数量。通常,将它设置为等于服务器上的处理器核心数是个好主意。您可以生成更多线程以允许同时处理更多请求,但工作线程会产生额外的内存开销——每个工作线程都会启动 rails 应用程序的副本,因此通常,您会使用线程来实现更高的吞吐量。

RAILS_MAX_THREADS 是一种设置每个工作线程将在后台使用的线程数的方法。在上面的示例中,min_threads_count 等于 max_threads_count,因此线程数是常量。如果您将它们设置为不同,它将从最小值扩展到最大值,但我还没有在野外看到它。

限制线程数量的原因有很多——您的解释器和响应时间:

  1. 如果您使用 MRI,您的线程会受到 GIL 的限制,因此它们不会 运行 并行。 MRI 通过上下文切换模拟并行执行。大量的线程将允许更多的同时连接,但平均响应时间会因为 GIL 而增加。
  2. 平台限制:即 heroku 有线程数限制 https://devcenter.heroku.com/articles/dynos#process-thread-limits, linux limits only the number of processes Maximum number of threads per process in Linux?
  3. 当代码不是线程安全的时,使用多个线程可能会导致不可预知的问题。这实际上是我的情况,所以我没有对线程数进行太多试验。

还有一个论点是慢速 IO 阻塞 ruby 进程并且不允许上下文切换(即调用外部服务,或动态生成大文件),但事实证明并非如此真 http://yehudakatz.com/2010/08/14/threads-in-ruby-enough-already/。但是优化您的体系结构以在后台完成尽可能多的工作始终是一个好主意。

This answer 将帮助您找到给定硬件的线程数与工作线程数的完美组合。

This shows如何进行基准测试以找到确切的数字。

总结一下: WORKERS_NUM 乘以 RAILS_MAX_THREADS 得到 puma 可以处理的最大同时连接数。如果数字太低,您的用户将在负载高峰期间看到超时。要在使用 MRI 的情况下获得最佳性能,您需要将 WORKERS_NUM 设置为核心数,并根据性能测试期间的平均响应时间找到最佳 RAILS_MAX_THREADS