我正在考虑将我们的 ruby 解释器更新为 JRuby,这非常令人头疼,因为我们不得不从我们的应用程序中删除任何 2.x 特定语法并求助于 ruby 1.9.3 兼容性。这不是世界末日。
到了运行应用程序的时候,我发现我们不能在集群模式下使用 Puma。问题是,鉴于过去几年对 MRI 的所有修复和更改,拥有“真实线程”的好处仍然有效吗?
更新
为了使这更客观,问题是,“最新版本的 MRI 是否不需要采用 JRuby 来实现与本地线程相同的好处?”
最新版本的 MRI 是否不需要采用 JRuby 来实现与本机线程相同的好处?
答案是不。它并没有否定需求,它取决于您在其他答案中提到的应用程序。
此外,JRuby 不允许您在集群模式下运行,但就您的问题而言,这并不是真正的问题,因为它是多线程和并行的。只需在单模式下运行所需的线程数即可。它应该非常好,如果不是更轻量级的话。
让我为您提供一些参考资料,这些参考资料可以提供更多见解并让您进一步挖掘。
这个答案讨论了 MRI 和 JRuby 使用 Puma(最多 40 个线程)测试并发请求的实验。它相当全面。
需要注意的是它只测试并发请求,但在控制器中没有竞争条件。但是,我认为您可以从本文删除 config.threadsafe 中实现测试!没有太多的努力。
JRuby 和 MRI 的区别在于 JRuby 可以并行执行代码。MRI 受 GIL 限制,一次只能执行一个线程。您可以在这篇文章中阅读有关 GIL 的更多信息,没人了解 GIL。
结果相当令人惊讶。MRI 比 JRuby 快。随意改进和添加比赛条件。
请注意,两者都是多线程的并且不是线程安全的。真正的区别在于 MRI 不能并行执行代码,而 JRuby 可以。
如果实验表明 MRI 速度更快,您可能会想说为什么我会回答“否”。
我认为我们需要更多的实验,尤其是现实世界的应用。
如果您认为 JRuby 应该更快,因为它可以并行执行代码,那么原因可能是:
确实取决于您使用 Web 服务器的情况(您应该对此有最好的理解)......如果您觉得您的产品在 MRI 下运行良好,而不是您可能没有那么多的并发性。与 Rubinius/JRuby 相比, puma 的README几乎解释了您在 MRI 下得到的结果:
在 MRI 上,有一个全局解释器锁 (GIL),可确保一次只能运行一个线程。但是,如果您正在执行大量阻塞 IO(例如对 Twitter 等外部 API 的 HTTP 调用),Puma 仍然通过允许阻塞 IO 并发运行来提高 MRI 的吞吐量(基于 EventMachine 的服务器,例如 Thin 关闭此功能,需要您可以使用特殊库)。你的旅费可能会改变。为了获得最佳吞吐量,强烈建议您使用带有真实线程的 Ruby 实现,例如 Rubinius 或 JRuby
... 所以一句话:**你可以在MRI下有多个线程,但你没有并行性**
恕我直言,这取决于您的应用程序做什么。
我已经在我的 Rails 应用程序上测试了 MRI/YARV 和 JRuby。由于该应用程序所做的大部分工作是路由 HTTP 请求、从数据库中获取数据、应用简单的业务逻辑并写入数据库,因此并行性并不是什么大问题。MRI 上的 Puma 确实处理用于阻塞 IO 操作(DB、API)的多线程。超出此范围的任务(图像处理、处理报告数据、调用外部 API 等)可能无论如何都应该由后台作业处理(我推荐https://github.com/brandonhilkert/sucker_punch)。
根据您的部署需要,内存消耗可能是一个更大的问题,而且 JRuby 非常需要内存。就我而言,几乎是 2 倍的内存。
如果您在 Heroku 上部署应用程序,您可能会发现能够在 1 个测功机上同时运行 2 个实例,从而获得更多收益。