提问人:pingu 提问时间:11/6/2010 最后编辑:Aamirpingu 更新时间:9/19/2016 访问量:96298
Ruby on Rails 服务器选项 [已关闭]
Ruby on Rails Server options [closed]
问:
为我的 Ruby on Rails 应用程序设置开发服务器的整个问题让我感到困惑。我敢肯定,有 WEBrick、Mongrel、Passenger、Apache、Nginx 等等,我不太了解它们所扮演的不同角色。
我开始使用 WEBrick,现在我使用 Mongrel 进行开发。这些服务器是独立的,还是位于Apache前面?
我读过 Passenger,但我真的不明白它是什么,该网站说“使 Ruby Web 应用程序的部署变得轻而易举”,它会取代 Mongrel 吗?它是否像 Capistrano 一样,也部署了 Web 应用程序?
请记住,我想测试 SSL,并且我相信 mongrel 不支持 SSL,最好的开发服务器设置是什么?
谢谢
答:
根据上下文,“部署”一词可以有两种含义。您还混淆了 Apache/Nginx 的角色和其他组件的角色。
历史说明:本文最初写于 2010 年 11 月 6 日,当时 Ruby 应用服务器生态系统受到限制。我在 2013 年 3 月 15 日更新了这篇文章,其中包含生态系统中的所有最新更新。
免责声明:我是应用程序服务器之一Phusion Passenger的作者之一。
Apache 与 Nginx
它们都是 Web 服务器。它们可以提供静态文件,但 - 使用正确的模块 - 也可以提供动态 Web 应用程序,例如用 PHP 编写的应用程序。Apache更受欢迎,功能更多,Nginx更小更快,功能更少。
Apache 和 Nginx 都不能为开箱即用的 Ruby Web 应用程序提供服务,为此,您需要将 Apache/Nginx 与某种附加组件结合使用,稍后将介绍。
Apache 和 Nginx 也可以充当反向代理,这意味着它们可以接受传入的 HTTP 请求并将其转发到另一个服务器,该服务器也使用 HTTP。当该服务器以 HTTP 响应时,Apache/Nginx 会将响应转发回客户端;您稍后将了解为什么这是相关的。
Mongrel 和其他生产应用服务器与 WEBrick 的对比
Mongrel 是一个 Ruby 的“应用程序服务器”:具体来说,这意味着 Mongrel 是一个应用程序,它:
- 将 Ruby 应用加载到其自己的进程空间中。
- 设置TCP套接字,使其能够与外界(例如Internet)通信。 Mongrel 侦听此套接字上的 HTTP 请求,并将请求数据传递给 Ruby Web 应用。
- 然后,Ruby Web 应用程序返回一个对象,该对象描述了 HTTP 响应应该是什么样子,Mongrel 负责将其转换为实际的 HTTP 响应(实际字节)并通过套接字将其发送回。
然而,Mongrel 已经过时了,现在它不再维护。较新的替代应用程序服务器包括:
- Phusion Passen(普西翁乘客)
- 独 角 兽
- 薄
- 美洲狮
- 特立尼达(仅限 JRuby)
- TorqueBox(仅限 JRuby)
我稍后会介绍它们,并描述它们彼此之间以及与 Mongrel 的不同之处。
WEBrick 与 Mongrel 做同样的事情,但区别在于:
- WEBrick 不适合生产,这与我之前提到的其他所有内容不同。WEBrick 完全是用 Ruby 编写的。Mongrel(以及大多数其他 Ruby 应用服务器)是 Ruby 的一部分,也是 C 的一部分(主要是 Ruby),但它的 HTTP 解析器是用 C 语言编写的,以提高性能。
- WEBrick 速度较慢且功能较差。它有一些已知的内存泄漏和一些已知的 HTTP 解析问题。
- WEBrick 通常只在开发过程中用作默认服务器,因为 WEBrick 默认包含在 Ruby 中。Mongrel 和其他应用服务器需要单独安装。不建议在生产环境中使用 WEBrick,尽管出于某种原因,Heroku 选择了 WEBrick 作为其默认服务器。他们以前使用过 Thin,所以我不知道他们为什么改用 WEBrick。
应用服务器和世界
目前所有的 Ruby 应用服务器都使用 HTTP,但是有些应用服务器可能通过端口 80 直接暴露给 Internet,而另一些则不然。
- 可直接暴露在互联网上的应用服务器:Phusion Passenger、Rainbows
- 可能不直接暴露于 Internet 的应用服务器:Mongrel、Unicorn、Thin、Puma。这些应用服务器必须放在反向代理 Web 服务器(如 Apache 和 Nginx)后面。
- 我对特立尼达和TorqueBox的了解还不够,所以我省略了它们。
为什么某些应用服务器必须放在反向代理后面?
- 某些应用服务器每个进程只能同时处理 1 个请求。如果要同时处理 2 个请求,则需要运行多个应用服务器实例,每个实例都为同一个 Ruby 应用提供服务。这组应用服务器进程称为应用服务器集群(因此得名 Mongrel 集群、精简集群等)。然后,您必须设置 Apache 或 Nginx 以反向代理到此群集。Apache/Nginx 将负责在集群中的实例之间分配请求(更多内容见“I/O 并发模型”一节)。
- Web 服务器可以缓冲请求和响应,保护应用服务器免受“慢速客户端”(不会很快发送或接受数据的 HTTP 客户端)的影响。您不希望应用服务器在等待客户端发送完整请求或接收完整响应时不执行任何操作,因为在此期间,应用服务器可能无法执行任何其他操作。Apache 和 Nginx 非常擅长同时做很多事情,因为它们要么是多线程的,要么是事件的。
- 大多数应用服务器可以提供静态文件,但不是特别擅长。Apache 和 Nginx 可以更快地做到这一点。
- 人们通常将 Apache/Nginx 设置为直接提供静态文件,但将与静态文件不对应的请求转发到应用服务器,这是很好的安全实践。Apache 和 Nginx 非常成熟,可以保护应用程序服务器免受(可能是恶意的)损坏请求的影响。
为什么有些应用服务器可以直接暴露在互联网上?
- Phusion Passenger 是一个与所有其他应用服务器截然不同的野兽。它的独特功能之一是它集成到 Web 服务器中。
- 《彩虹》的作者公开表示,直接将其暴露在互联网上是安全的。作者相当确定 HTTP 解析器(和类似)中没有漏洞。尽管如此,作者不提供任何保证,并表示使用风险自负。
应用程序服务器比较
在本节中,我将比较我提到的大多数应用程序服务器,但不包括 Phusion Passenger。Phusion Passenger 是一头与众不同的野兽,我给它一个专门的部分。我还省略了 Trinidad 和 TorqueBox,因为我对它们不够了解,但无论如何,它们只有在使用 JRuby 时才有意义。
- 杂种是相当光秃秃的骨头。如前所述,Mongrel 是纯单线程多进程,因此它仅在集群中有用。没有进程监控:如果集群中的进程崩溃(例如,由于应用程序中的错误),则需要手动重新启动它。人们倾向于使用外部过程监控工具,例如 Monit 和 God。
- 独角兽是 Mongrel 的一个分支。它支持有限的进程监控:如果进程崩溃,主进程会自动重新启动。它可以使所有进程在单个共享套接字上侦听,而不是为每个进程使用单独的套接字。这简化了反向代理配置。与 Mongrel 一样,它是纯粹的单线程多进程。
- Thin 利用 EventMachine 库使用事件 I/O 模型。除了使用 Mongrel HTTP 解析器之外,它不以任何方式基于 Mongrel。它的集群模式没有进程监控,因此您需要监控崩溃等。没有类似独角兽的共享套接字,因此每个进程都在自己的套接字上侦听。理论上,Thin 的 I/O 模型允许高并发,但在 Thin 使用的大多数实际情况下,一个 Thin 进程只能处理 1 个并发请求,因此您仍然需要一个集群。有关此特殊属性的更多信息,请参阅“I/O 并发模型”一节。
- Puma 也是从 Mongrel 分叉而来的,但与 Unicorn 不同的是,Puma 被设计为纯粹的多线程。因此,目前没有内置群集支持。您需要特别注意确保可以使用多个内核(有关此内容的更多信息,请参阅“I/O 并发模型”一节)。
- Rainbows 通过使用不同的库来支持多种并发模型。
Phusion Passen(普西翁乘客)
Phusion Passenger 的工作方式与所有其他产品截然不同。Phusion Passenger 直接集成到 Apache 或 Nginx 中,因此可以与 Apache 的 mod_php 进行比较。就像mod_php允许Apache为PHP应用程序提供服务一样,Phusion Passenger允许Apache(以及Nginx!)为Ruby应用程序提供服务,几乎是神奇的。Phusion Passenger 的目标是让一切变得尽可能少的麻烦。
无需为您的应用程序启动进程或集群,并使用 Phusion Passenger 配置 Apache/Nginx 以向进程/集群提供静态文件和/或反向代理请求,您只需要:
- 您可以编辑 Web 服务器配置文件并指定 Ruby 应用程序的“public”目录的位置。
- 没有步骤 2。
所有配置都在 Web 服务器配置文件中完成。Phusion Passenger 几乎可以自动化一切。无需启动集群和管理进程。启动/停止进程,在进程崩溃时重新启动进程等 - 所有这些都是自动化的。与其他应用程序服务器相比,Phusion Passenger 的活动部件要少得多。这种易用性是人们使用Phusion Passenger的主要原因之一。
与其他应用服务器不同,Phusion Passenger主要是用C++编写的,因此速度非常快。
Phusion Passenger 还有一个企业版,具有更多功能,例如自动滚动重启、多线程支持、抗部署错误等。
由于上述原因,Phusion Passenger是目前最受欢迎的Ruby应用服务器,为超过150,000个网站提供支持,包括纽约时报,皮克斯,Airbnb等大型网站。
Phusion Passenger 与其他应用服务器
Phusion Passenger 提供了更多功能,并提供了与其他应用程序服务器相比的许多优势,例如:
- 根据流量动态调整进程数。我们在资源有限的服务器上运行了大量的 Rails 应用程序,这些应用程序不面向公众,而且我们组织中的人们每天最多只使用几次。像 Gitlab、Redmine 等。 Phusion Passenger 可以在不使用时关闭这些进程,并在使用时启动它们,从而为更重要的应用程序提供更多资源。使用其他应用服务器时,您的所有进程始终处于打开状态。
- 根据设计,某些应用服务器不擅长某些工作负载。例如,Unicorn 专为快速运行的请求而设计:请参阅 Unicorn 网站部分“在某些情况下更糟”。
Unicorn 不擅长的工作负载包括:
- 流式处理工作负载(例如 Rails 4 实时流式处理或 Rails 4 模板式流式处理)。
- 应用在其中执行 HTTP API 调用的工作负载。
Phusion Passenger Enterprise 4 或更高版本中的混合 I/O 模型使其成为此类工作负载的绝佳选择。
- 其他应用服务器要求用户为每个应用程序至少运行一个实例。相比之下,Phusion Passenger 在单个实例中支持多个应用程序。这大大减少了管理开销。
- 自动用户切换,方便的安全功能。
- Phusion Passenger 支持许多 MRI Ruby、JRuby 和 Rubinius。Mongrel、Unicorn 和 Thin 仅支持 MRI。彪马还支持所有 3 种。
- Phusion Passenger 实际上支持的不仅仅是 Ruby!它还支持 Python WSGI,因此它还可以运行 Django 和 Flask 应用程序。事实上,Phusion Passenger 正朝着成为多语言服务器的方向发展。待办事项列表中的 Node.js 支持。
- 带外垃圾回收。Phusion Passenger 可以在正常的请求/响应周期之外运行 Ruby 垃圾回收器,从而可能将请求时间减少数百毫秒。Unicorn 也有类似的功能,但 Phusion Passenger 的版本更灵活,因为 1)它不限于GC,可用于任意工作。 2) Phusion Passenger 的版本适用于多线程应用程序,而 Unicorn 的版本则不然。
- 自动滚动重启。在 Unicorn 和其他服务器上滚动重启需要一些脚本工作。Phusion Passenger Enterprise 以这种方式为您完全自动化。
有更多的功能和优势,但列表真的很长。您应该参考全面的Phusion Passenger手册(Apache版本,Nginx版本)或Phusion Passenger网站以获取信息。
I/O 并发模型
- 单线程多进程。传统上,这是 Ruby 应用服务器最流行的 I/O 模型,部分原因是 Ruby 生态系统中的多线程支持非常糟糕。每个进程一次只能处理 1 个请求。Web 服务器在进程之间进行负载平衡。这个模型非常健壮,程序员几乎没有机会引入并发错误。但是,其 I/O 并发性非常有限(受进程数量的限制)。此模型非常适合快速、运行时间较短的工作负载。它非常不适合缓慢、长时间运行的阻塞 I/O 工作负载,例如涉及调用 HTTP API 的工作负载。
- 纯多线程。如今,Ruby 生态系统具有出色的多线程支持,因此这种 I/O 模型变得非常可行。多线程支持高 I/O 并发性,使其适用于短运行和长运行阻塞 I/O 工作负载。程序员更有可能引入并发错误,但幸运的是,大多数 Web 框架的设计方式仍然不太可能。然而,需要注意的一点是,由于使用了全局解释器锁 (GIL),即使有多个线程,MRI Ruby 解释器也无法利用多个 CPU 内核。您可以使用多个多线程进程来解决此问题,因为每个进程都可以利用一个 CPU 内核。JRuby 和 Rubinius 没有 GIL,因此它们可以在单个进程中充分利用多个内核。
- 混合多线程多进程。主要由 Phusion Passenger Enterprise 4 及更高版本实现。您可以轻松地在单线程多进程、纯多线程甚至多个进程之间切换,每个进程都有多个线程。这种模式提供了两全其美的优势。
- 事件。该模型与前面提到的模型完全不同。它允许非常高的 I/O 并发性,因此非常适合长时间运行的阻塞 I/O 工作负载。要使用它,需要应用程序和框架的显式支持。但是,所有主要的框架,如 Rails 和 Sinatra 都不支持事件代码。这就是为什么在实践中,精简进程仍然不能一次处理超过 1 个请求,这使得它的行为实际上与单线程多进程模型相同。有一些专门的框架可以利用事件 I/O,例如 Cramp。
最近在 Phusion 博客上发布了一篇文章,内容是关于根据工作负载优化进程和线程数。请参阅调整 Phusion Passenger 的并发设置。
卡皮斯特拉诺
Capistrano 是完全不同的东西。在前面的所有章节中,“部署”是指在应用程序服务器中启动 Ruby 应用程序的行为,以便访问者可以访问它,但在此之前,通常需要做一些准备工作,例如:
- 将 Ruby 应用程序的代码和文件上传到服务器计算机。
- 安装应用所依赖的库。
- 设置或迁移数据库。
- 启动和停止应用可能依赖的任何守护程序,例如 Sidekiq/Resque 工作线程等。
- 设置应用程序时需要执行的任何其他操作。
在 Capistrano 的上下文中,“部署”是指完成所有这些准备工作。Capistrano 不是应用程序服务器。相反,它是一种自动化所有准备工作的工具。每次部署新版本的应用程序时,您都会告诉 Capistrano 您的服务器在哪里以及需要运行哪些命令,Capistrano 将负责为您将 Rails 应用程序上传到服务器并运行您指定的命令。
Capistrano 始终与应用程序服务器结合使用。它不会取代应用程序服务器。反之亦然,应用程序服务器不会取代 Capistrano,它们可以与 Capistrano 结合使用。
当然,您不必使用 Capistrano。如果您更喜欢使用 FTP 上传 Ruby 应用程序,并且每次都手动运行相同的命令步骤,那么您可以这样做。其他人已经厌倦了它,所以他们在 Capistrano 中自动执行这些步骤。
评论