多进程VS多线程服务器最受益的是什么?

Rya*_*yan 24 ruby multithreading ruby-on-rails unicorn puma

任何人都可以解释每个并发方法的瓶颈是什么?

Unicorn(基于进程)和Puma(基于线程)的服务器.

每种方法都更喜欢CPU内核吗?线程?或者只是时钟速度?还是特殊的组合?

如何确定使用专用服务器时所需的最佳CPU特性?

如何确定Unicorn情况下的最佳工人数量,或者在Puma的情况下确定线程数量?

Stu*_*son 56

Unicorn是基于进程的,这意味着每个ruby实例都必须存在于自己的进程中.对于每个进程,这可能在500mb的范围内,这将很快耗尽系统资源.基于线程的Puma将不会使用相同数量的内存来理论上获得相同的并发数量.

Unicorn,即运行多个进程,将在不同进程之间具有并行性.这受到CPU内核的限制(更多内核可以同时运行更多进程),但内核将在活动进程之间切换,因此可以运行4到8个进程(无论您拥有多少个进程).您将受到机器内存的限制.直到最近,ruby还没有写入时友好,这意味着每个进程都有自己的继承内存(unicorn是一个preforking服务器).Ruby 2.0是写时复制友好的,这可能意味着独角兽实际上不必在内存中加载所有子进程.我不是100%清楚这一点.阅读有关写入的副本,并查看jessie storimer的"使用unix进程"这本很棒的书.我很确定他在那里覆盖了它.

Puma是一个线程服务器.MRI Ruby由于全局解释器锁(GIL),一次只能运行一个CPU绑定任务(参见ruby tapas第127集,parallel fib).它将在线程之间进行上下文切换,但只要它是一个CPU绑定任务(例如数据处理),它就只会运行一个执行线程.如果您使用不同的Ruby实现(如JRuby或Rubinius)运行服务器,这会很有趣.他们没有GIL,可以并行处理大量信息.JRuby非常快,虽然Rubinius与MRI相比较慢,但多线程Rubinius处理数据的速度比MRI快.在非阻塞IO,然而,(如写入数据库,使得Web请求),MRI将上下文切换到非执行线程,做在那里工作,然后在已返回的信息切换回之前的线程.

对于Unicorn,我会说瓶颈是内存和时钟速度.对于Puma,我会说瓶颈是您选择的解释器(MRI vs Rubinius或JRuby)以及服务器正在进行的工作类型(许多cpu绑定任务与非阻塞IO).

这场辩论有很多很好的资源.查看Jessie Storimer关于这些主题的书籍,使用ruby线程使用unix进程 ; 阅读 ryan tomayko 关于preforking服务器这个快速摘要,并谷歌周围的更多信息.

在你的情况下,我不知道Unicorn或Puma的最佳工人数量是多少.最好的办法是运行性能测试并做适合自己的事情.没有一种尺寸适合所有人.(虽然我认为美洲狮的标准是使用16个线程的池并锁定它)


lam*_*ont 5

Puma实际上是多线程和多进程的.您可以在"群集模式"中调用它,它将生成多个分叉的工作人员,这些工作人员将在MRI上的不同核心上运行.由于Puma是多线程的,因此可能适合运行与服务器上的核心数相等的多个进程.所以对于4核服务器来说这样的事情是合适的:

puma -t 8:32 -w 4 --preload
Run Code Online (Sandbox Code Playgroud)

这将处理多达32个并发线程,同时在CPU上运行最多4个线程,并且应该能够最大化服务器上​​的CPU资源.该--preload参数预加载应用程序并利用ruby 2.0 COW对垃圾收集的改进来减少RAM使用.

如果您的应用花费大量时间等待其他服务(搜索服务,数据库等),那么这将是一个很大的改进.当一个线程阻塞时,同一进程中的另一个线程可以抓住CPU并继续工作.在此示例中,您最多可以并行支持32个请求,而只需要在RAM中运行4个进程.

使用Unicorn,您将不得不分叉32个工作人员,这将在RAM中运行32个进程,这非常浪费.

如果您的所有应用程序都是CPU运算,那么这将是非常低效的,您应该减少独角兽的数量,并且Puma优于Unicorn的好处将会减少.但在Unicorn案例中,您必须对应用程序进行基准测试并找出正确的数字.Puma将倾向于通过产生更多线程来优化自身,其性能应该不低于Unicorn(在纯CPU情况下)到比Unicorn好得多(在应用程序睡眠很多的情况下).

当然,如果你使用Rubinius或JRuby,那么它就没有竞争,你可以产生一个运行多核并处理所有32个线程的进程.

TL; DR是因为Puma实际上使用这两种模型,所以我认为Unicorn不会优于Puma.

当然,我对Puma与Unicorn在现实世界中运行生产软件的可靠性一无所知.需要关注的一件事是,如果你在一个线程中乱写任何全局状态,它可能会影响同时执行的其他请求,这可能会产生不确定的结果.由于Unicorn不使用线程,因此没有并发问题.我希望到目前为止,Puma和Rails在并发问题方面都很成熟,并且Puma可用于生产.但是,我不一定希望我在GitHub上找到的每个rails插件和rubygem都是线程安全的,并且预计还需要做一些额外的工作.但是,一旦你成功地在第三方库中找到线程问题,你可能已经足够大,以至于你无法负担运行这么多Unicorn进程的RAM成本.OTOH,我理解并发错误,我对Ruby很好,因此调试成本对我来说可能比在云中购买RAM的成本要低得多.因人而异.

另请注意,我不确定您是否应该计算超线程内核或物理内核来估计传递给'-w'的值,并且您需要自己进行性能测试,以及性能测试用于-t的值.虽然即使你运行的进程数量是你需要的两倍,但是内核中的进程调度程序应该能够毫无困难地处理它,直到你使CPU饱和为止,无论如何你都会遇到更大的问题.我可能会建议为每个超线程核心启动一个过程(在MRI上).