multithreading Puma中的Workers和Threads有什么区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24280743/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 01:26:10  来源:igfitidea点击:

What is the difference between Workers and Threads in Puma

multithreadingherokuruby-on-rails-4puma

提问by Nick Ginanto

What is the difference between a puma worker and a puma thread in context of a heroku dyno?

在heroku dyno的上下文中,puma worker和puma线程有什么区别?

What I know (please correct me if I am wrong):

我所知道的(如果我错了,请纠正我):

  • Thin is not concurrent, so a web process can only do one request at a time

  • In unicorn, I know I can have several unicorn workers in one process to add concurrency.

  • Thin 不是并发的,所以一个 web 进程一次只能做一个请求

  • 在 unicorn 中,我知道我可以在一个进程中使用多个 unicorn worker 来增加并发性。

But in puma there is threads and workers.. Isn't a worker a thread inside the puma process?

但是在 puma 中有线程和工人.. 工人不是 puma 进程中的线程吗?

Can I use more workers/threads to add web concurrency in Heroku?

我可以使用更多的工作线程/线程在 Heroku 中添加网络并发吗?

采纳答案by robert_murray

As the other answer states, this Heroku articleis pretty good with explanations of certain configuration items.

正如另一个答案所述,这篇Heroku 文章很好地解释了某些配置项。

However if you need to tune your application on Heroku, or anywhere, then it pays to know how things work.

但是,如果您需要在 Heroku 或任何地方调整您的应用程序,那么了解它的工作原理是值得的。

I think you are almost correct when you say "a worker is a thread inside the puma process", I believe a worker is an operating system level process forked from puma which then can use threads internally.

当你说“一个工人是 puma 进程中的一个线程”时,我认为你几乎是正确的,我相信一个工人是一个操作系统级进程,从 puma 派生出来,然后可以在内部使用线程。

As far as I understand - puma will fork its operating system process however many times you set via workersconfiguration to respond to http requests. This gives you parallelism in terms of handling multiple requests but this will usually take up more memory as it will 'copy' your application code for each worker.

据我了解 - 无论您通过workers配置设置多少次以响应 http 请求,puma 都会分叉其操作系统进程。这在处理多个请求方面为您提供了并行性,但这通常会占用更多内存,因为它会为每个工作人员“复制”您的应用程序代码。

Each puma worker will then use multiple threads within its OS process depending on the threadsconfiguration. These add concurrency by allowing the puma process to respond to multiple requests itself so that if one thread is blocked, ie processing a request, it can handle a new request with another thread. As stated, this requires your entire application to be threadsafe so that, for example any global configuration from one request does not 'leak' into another.

然后,每个 puma worker 将根据threads配置在其操作系统进程中使用多个线程。这些通过允许 puma 进程自己响应多个请求来增加并发性,这样如果一个线程被阻塞,即处理一个请求,它可以用另一个线程处理一个新请求。如前所述,这要求您的整个应用程序都是线程安全的,例如,来自一个请求的任何全局配置都不会“泄漏”到另一个请求中。

You would tune puma so that the number of workers was adequate for the number of CPUs and memory available and then tune the threads dependant on how much you would want to saturate the host running your application and how your application behaves - more does not always equal faster/more request throughput.

您将调整 puma 以便工作程序的数量足以满足可用的 CPU 和内存数量,然后根据您希望使运行应用程序的主机达到饱和程度以及应用程序的行为方式来调整线程——更多并不总是等于更快/更多的请求吞吐量。

回答by jordelver

This is a big area and I am not an expert, however...

这是一个很大的领域,我不是专家,但是......

Puma can spawn many workers, and each worker can use many threads to process the request.

Puma 可以产生很多 worker,每个 worker 可以使用很多线程来处理请求。

Unicorn does not have threads as far as I know, it just has the worker model.

据我所知,独角兽没有线程,它只有工人模型。

If you use threads though, you need to make sure that your code is thread safe. This means Rails, any gem you rely on, and your own code.

如果您使用线程,则需要确保您的代码是线程安全的。这意味着 Rails、您依赖的任何 gem 以及您自己的代码。

For maximum performance, you might also want to look into JRubyor Rubiniuswhich have proper thread support. MRI is restricted by its GIL.

为了获得最佳性能,您可能还想查看具有适当线程支持的JRubyRubinius。MRI 受其 GIL 限制。

There is a good article on Herokuwhich explains how Puma uses workers and threads. You should probably read that and ignore me :)

Heroku 上有一篇很好的文章,解释了 Puma 如何使用工作线程和线程。您可能应该阅读并忽略我:)

回答by Donato

I just want to emphasize the most important line of the Heroku/Puma article that was referenced here:

我只想强调这里引用的 Heroku/Puma 文章中最重要的一行:

Rails maintains its own database connection pool, with a new pool created for each worker process. Threads within a worker will operate on the same pool.

Rails 维护自己的数据库连接池,并为每个工作进程创建一个新池。工作线程中的线程将在同一个池中运行。

It states that each Worker will have its own Pool. However:

它指出每个 Worker 将拥有自己的 Pool。然而:

Threads within a worker will operate on the same pool.

工作线程中的线程将在同一个池中运行。

This is very important to understand. If a Puma Worker utilizes 5 threads per worker, then the database.yml must be configured to a connection pool of 5, since each thread could possibly establish a database connection.

理解这一点非常重要。如果 Puma Worker 每个 Worker 使用 5 个线程,那么 database.yml 必须配置为 5 个连接池,因为每个线程都可能建立一个数据库连接。

Since each Worker is spawned by a system fork(), the new worker will have its own set of 5 threads to work with, and thus for the new Rails instance created, the database.yml will still be set to a connection pool of 5.

由于每个 Worker 都是由系统 fork() 生成的,因此新的 Worker 将拥有自己的 5 个线程集来使用,因此对于创建的新 Rails 实例,database.yml 仍将设置为 5 个连接池.

Now the database.yml connection pool and your actual database pool are two different things. The TOTAL connections to your database will need to use a specific formula that the Heroku docs mention:

现在 database.yml 连接池和您的实际数据库池是两个不同的东西。与数据库的 TOTAL 连接需要使用 Heroku 文档中提到的特定公式:

A good formula for determining the number of connections each application will require is to multiply the RAILS_MAX_THREADS by the WEB_CONCURRENCY.

确定每个应用程序需要的连接数的一个很好的公式是将 RAILS_MAX_THREADS 乘以 WEB_CONCURRENCY。

What this means is if you are using 2 Workers, each with 5 threads, then 2 * 5 = 10, so your database must be configured to accept 10 concurrent connections.

这意味着如果您使用 2 个 Worker,每个 5 个线程,则 2 * 5 = 10,因此您的数据库必须配置为接受 10 个并发连接。