Puma 工人与单独的 EC2 实例
puma workers vs separate ec2 instances
我来自 Java/Tomcat 堆栈并且是 RoR 堆栈的新手。我正在尝试了解有关 puma 配置的一些概念。我已经阅读 this and this 但我仍然不清楚工人术语。
我知道工人会导致子进程 运行 puma。因此,在使用多核实例时,本质上允许您实现并行性。但是您也可以通过启动尽可能多的 ec2 单核实例来做同样的事情吗?
另外,如果实例不是多核的,那么设置 workers > 0 是否有意义。
这里的任何信息都会对我有很大帮助。谢谢!
在Puma的上下文中,worker和threads都是用来实现并发的,这样Puma就可以处理请求,而不必一直等待前面的请求完成。一个好的配置需要在工作者和线程的数量之间找到一个很好的平衡,并且需要考虑部署的应用程序的几个方面:
工人:
- 具有更大的内存开销,因为每个分叉进程都需要自己的内存(由于(https://en.wikipedia.org/wiki/Copy-on-write),这在 Linux 上有所缓解,但仍然是一个因素)
- 当有多个内核可用时允许并行。当处理请求的计算量很大时,这主要是一个问题——这是要避免的事情——如果请求需要执行一些繁重的计算,最好使用像 (https://github.com/mperham/sidekiq)[= 这样的库将其移动到后台作业40=]
- 不能在 JRuby 上使用,因为它不支持分叉
线程
- 每个工作进程的配置线程数量将为 运行 - 这意味着如果您有
workers x
和 threads y
那么您将获得总共 x * y
个请求处理线程
- 共享内存以减少内存占用(尽管这里也有问题:(https://www.speedshop.co/2017/12/04/malloc-doubles-ruby-memory.html)
- 在默认 Ruby 实现的 MRI 上,由于 GIL,线程不允许并行执行 Ruby 代码 - 这不应该是一个大问题,因为 GIL 不是在等待 IO 期间被锁定,这是将花费大量执行时间的地方 - 访问数据库、与 API 通信等。
- 在JRUBY线程上可以实现并行。
- 如果您的应用不是线程安全的,则无法使用。 Rails 本身是线程安全的,但您无法保证应用程序依赖的任何 3d 方代码或应用程序代码本身。如果应用程序不是线程安全的,这里的答案很简单——不要使用线程(意味着将最小和最大线程配置为 1)。缺乏线程安全是一种情况,即使在单个核心实例上,多工作者配置也有意义。
- 对于任何数量的线程,您都需要确保连接池中有足够的数据库连接。这通常意味着将 Rails 连接池大小设置为您在工作进程中 运行 的线程数。
将多个工作人员与部署到多个 EC2 实例进行比较会遗漏一部分情况:当将 Puma 与多个工作人员一起使用时,有一个主 Puma 进程侦听端口并将每个请求路由到可用的工作进程。当您有多个 EC2 实例时,您需要以某种方式处理它们之间的负载平衡——在 AWS 的情况下可能是 ELB 或 ALB。部署到多个实例和负载平衡是部署任何重要 Web 应用程序的正确方法,但这不应该阻止您通过工作程序和线程更好地利用实例资源。
我建议尝试配置 worker 和线程,首先将 worker 的内核数和线程数设置为 10 - 如果您遇到内存使用问题或资源利用不足,则进行调整。
我来自 Java/Tomcat 堆栈并且是 RoR 堆栈的新手。我正在尝试了解有关 puma 配置的一些概念。我已经阅读 this and this 但我仍然不清楚工人术语。
我知道工人会导致子进程 运行 puma。因此,在使用多核实例时,本质上允许您实现并行性。但是您也可以通过启动尽可能多的 ec2 单核实例来做同样的事情吗?
另外,如果实例不是多核的,那么设置 workers > 0 是否有意义。
这里的任何信息都会对我有很大帮助。谢谢!
在Puma的上下文中,worker和threads都是用来实现并发的,这样Puma就可以处理请求,而不必一直等待前面的请求完成。一个好的配置需要在工作者和线程的数量之间找到一个很好的平衡,并且需要考虑部署的应用程序的几个方面:
工人:
- 具有更大的内存开销,因为每个分叉进程都需要自己的内存(由于(https://en.wikipedia.org/wiki/Copy-on-write),这在 Linux 上有所缓解,但仍然是一个因素)
- 当有多个内核可用时允许并行。当处理请求的计算量很大时,这主要是一个问题——这是要避免的事情——如果请求需要执行一些繁重的计算,最好使用像 (https://github.com/mperham/sidekiq)[= 这样的库将其移动到后台作业40=]
- 不能在 JRuby 上使用,因为它不支持分叉
线程
- 每个工作进程的配置线程数量将为 运行 - 这意味着如果您有
workers x
和threads y
那么您将获得总共x * y
个请求处理线程 - 共享内存以减少内存占用(尽管这里也有问题:(https://www.speedshop.co/2017/12/04/malloc-doubles-ruby-memory.html)
- 在默认 Ruby 实现的 MRI 上,由于 GIL,线程不允许并行执行 Ruby 代码 - 这不应该是一个大问题,因为 GIL 不是在等待 IO 期间被锁定,这是将花费大量执行时间的地方 - 访问数据库、与 API 通信等。
- 在JRUBY线程上可以实现并行。
- 如果您的应用不是线程安全的,则无法使用。 Rails 本身是线程安全的,但您无法保证应用程序依赖的任何 3d 方代码或应用程序代码本身。如果应用程序不是线程安全的,这里的答案很简单——不要使用线程(意味着将最小和最大线程配置为 1)。缺乏线程安全是一种情况,即使在单个核心实例上,多工作者配置也有意义。
- 对于任何数量的线程,您都需要确保连接池中有足够的数据库连接。这通常意味着将 Rails 连接池大小设置为您在工作进程中 运行 的线程数。
- 每个工作进程的配置线程数量将为 运行 - 这意味着如果您有
将多个工作人员与部署到多个 EC2 实例进行比较会遗漏一部分情况:当将 Puma 与多个工作人员一起使用时,有一个主 Puma 进程侦听端口并将每个请求路由到可用的工作进程。当您有多个 EC2 实例时,您需要以某种方式处理它们之间的负载平衡——在 AWS 的情况下可能是 ELB 或 ALB。部署到多个实例和负载平衡是部署任何重要 Web 应用程序的正确方法,但这不应该阻止您通过工作程序和线程更好地利用实例资源。
我建议尝试配置 worker 和线程,首先将 worker 的内核数和线程数设置为 10 - 如果您遇到内存使用问题或资源利用不足,则进行调整。