Puma 在使用 Nginx 的 EC2 实例上为 Rails 应用程序停止 运行(使用 Capistrano/Capistrano Puma)

Puma Stops Running for Rails App on EC2 Instance with Nginx (using Capistrano/Capistrano Puma)

我的首要问题是,我怎样才能让 Puma 停止失败。但这实际上是由许多小问题组成的。我将对每个问题进行编号并加粗,以尝试使这个问题可以回答。

我在 t2.nano 的 EC2 实例上托管 Rails 应用程序。诚然,这是一个非常小的盒子——但我不希望我的网站收到任何流量。我使用 Capistrano 和 Capistrano Puma 通过 Nginx 和 Puma 成功配置了所有内容。一切都很好,直到有一天我去我的网站看到 Nginx 504 消息。

我打开Nginx错误日志,发现无法连接Puma:

connect() to unix:/home/deploy/myapp/shared/tmp/sockets/puma.sock failed (111: Connection refused) while connecting to upstream, client: xxx.xxx.xxx.xxx, server: localhost, request: "GET / HTTP/1.0", upstream: "http://unix:/home/deploy/myapp/shared/tmp/sockets/puma.sock:/500.html", host: "myapp.com"

调试这个,我得知 Puma 已经停止 运行。这就是 Nginx 无法连接到它的原因。我觉得这里有两个问题:第一,Puma不应该停下来运行。服务器很小,但是没有流量。第二,当 Puma 确实失败时,它应该优雅地重新启动。不过,我现在只关注第一个问题。因为如果 Puma 不断地重新启动,那么有时它会以一种严厉的方式杀死进程似乎是合理的。

为了调试它,我打开了 htop。果然,机器 运行 没有任何可用内存。这是有道理的——我是 运行 数据库、rails 应用程序、网络服务器和内存缓存在一台微型机器上。它使 运行 内存不足并杀死 Puma。

我查看了使用 Capistrano 设置的 Puma 配置。在 config/deploy.rb 我有这些行--

set :puma_threads, [0, 8]
set :puma_workers, 0

我阅读了所有关于 puma_workers 和 puma_threads 的内容。我还了解到 Nginx 有自己的 workers。 Puma 工艺非常昂贵。 Puma 之所以酷,是因为它是适当的多线程——因此独立进程非常棒。听起来每个工人都有自己的一组线程——所以如果有 4 个工人和 8 个线程,就会有 32 个进程。但就我而言,我想使用很少的内存。 2 个过程对我来说听起来不错。 1。我对工人和线程的理解正确吗?

我更新了 config/deploy.rb 文件并部署了 0 puma_workers 和 min=0,max=2 线程。

看来 Nginx 的配置在这里:/etc/nginx/nginx.conf。 Puma 的配置在这里:/home/deploy/myapp/shared/puma.rb。我本以为我在 config/deploy.rb 中的更新会让 Capistano 编辑配置文件。运气不好——我的最小、最大线程数仍设置为 0.8。 2。使用 Capistano 时尝试通过 config/deploy.rb 更新这些值是否正确?

还有--我打开nginx.conf看到了worker_processes 4;3。这是我安装 Nginx 时设置为 4 还是 Capistano 设置了这个默认值?

我打开 htop,果然我有很多 Puma 进程。因此,我手动编辑了我的配置文件并重新启动了 Puma 和 Nginx。

我将 Nginx worker 的数量从 4 个更改为 1 个。在 htop 中查看,这有效。我现在只有 1 个 Nginx worker。然而,Nginx workers 从来都不是很昂贵(与 Puma 线程相比)。所以我认为这并不重要。

但是,仍然有 2 个以上的 Puma 线程——有 6 个。开玩笑,我将最小线程数从 0 更改为 1——我认为 0 不是一个可能的数字,所以可能是设置默认值。这样Puma进程数增加到9个,我也试过把puma_workers的数量改成1个,同理,进程数增加了。 4。拥有 0 个线程 and/or worker 是什么意思?

然后我尝试手动杀死一个 puma 进程 (sudo kill xxxxx),然后 所有 个 Puma 进程都死了。

5.我必须做什么才能只有 2 个 puma 进程?

如您所见,我对 Puma 的了解不是很好,Puma 与 Nginx 与 Capistano 之间的界限也不清楚。任何帮助是极大的赞赏。我没能找到关于这个问题的好资源。

这是我学到的--

  • 如果 Puma 停止工作,请确保您有足够的内存来处理指定数量的工作线程和线程。每个 Puma 工艺都非常昂贵。
  • 如果你设置 0 个工人,Puma 将不会 运行 在集群模式下。建议 运行 使用集群模式进行 MRI。
  • 线程是按集群设置的。如果您有 2 个作品和 0.8 个线程,这意味着您将有两个作品,每个作品将有 1 到 8 个线程。
  • Puma 除了线程之外还使用进程。 Puma 有一个父进程的 PID。如果您使用集群模式,它有一个 PID 来管理集群。如果您使用的是集群模式,它还有一个用于每个集群的 PID。然后,运行 其他任务(每个集群)有固定数量的 PID。没有集群模式,有 5 个固定的 PID。集群模式下,有7个固定的PID。
  • 这就是说——如果您看到的进程比您预期的多,这就是原因。另外——当你添加一个新的工作人员时,你会添加大量昂贵的流程。确保你有 space。 我有一个小应用程序,在 1 个工作人员和 min=1,max=4 线程的情况下,一切似乎都运行良好。最多 8 个线程似乎是我一直在杀死 puma 的原因。

回答我原来的问题--

  1. 是的,上面关于worker和threads的解释是正确的。
  2. capistrano-puma 似乎只在第一次部署时设置 puma 配置。
  3. 我认为 nginx 配置是在安装 nginx 时创建的。
  4. 0 个工人意味着你 运行ning puma 没有集群模式。不可能有 0 个线程。我相信 0,8 与 1,8 相同。
  5. 除了您请求的线程之外,Puma 还需要 运行 进程。 puma 运行 不可能只有 2 或 3 个 PID。这些过程 运行 添加任务。

一名 Puma 嫌疑人被处以绞刑

Puma 的特点是它是唯一一个鼓励在 MRI 中使用线程的主流项目 Ruby(嗯,无论如何,Heroku 鼓励)。

这就是为什么我们有时会看到 Puma 工作人员的说法,他们认为 Puma 存在各种问题,而问题出在其他地方,而且确实存在,而且只影响 Puma :P

“我们”在过去发现并修复了一些非常古怪和令人讨厌的 Ruby GC 问题,这些问题是在 Ruby MRI 中大量使用线程时出现的一些古怪的极端情况(记住 http://blog.skylight.io/hunting-for-leaks-in-ruby/) 谁能说这不是人们归咎于 Puma 的最后一个怪异问题?

尝试禁用线程一段时间,看看效果如何,然后告诉我们,也许兔子又躺在那儿了

解释线程与集群模式与工作者的文档

Thread pool 下,文档解释了如何设置工作线程的数量。请记住,Puma is/was 主要是 JRuby 的东西,MRI 支持和分叉只是后来才添加的,文档中配置条目的顺序(如何设置线程之前如何设置分叉) 是这个的结果。

文档状态:

Puma utilizes a dynamic thread pool which you can modify. You can set the minimum and maximum number of threads that are available in the pool with the -t (or --threads) flag:

Puma 2 offers clustered mode, allowing you to use forked processes to handle multiple incoming requests concurrently, in addition to threads already provided.

意思是,Puma 将始终线程,这就是它的作用,如果您告诉它执行 0/1 个线程,它就会执行 1 个线程,以便它可以处理请求。

此外,如果您将工作程序(进程)的数量设置为 > 1,Puma 将 运行 处于“集群模式”,这意味着它将分叉并且每个分叉都将线程化,

-w 3 -t4:4 将产生 3 个进程 运行 每个进程有 4 个线程,允许您同时处理 12 个请求。

Puma 文档没有具体说明 Puma 内部将使用哪些进程和多少进程,但有根据的猜测是它至少需要 运行 所有工作进程 + 1 个主进程管理它们、向它们传送数据、启动它们、停止它们、引导它们的日志等。