提问



为我的Ruby on Rails应用程序设置开发服务器的整个问题让我很困惑。我确信有WEBrick,Mongrel,Passenger,Apache,Nginx等等,而且我不太了解他们扮演的不同角色。


我开始使用WEBrick,现在我使用Mongrel进行开发。这些服务器是独立的,还是它们位于Apache之前?


我读过有关Passenger的内容,我不太明白它是什么,该网站说让Ruby Web应用程序的部署变得轻而易举,它是否取代了Mongrel?它是否像Capistrano一样,它还部署了Web应用程序?


请记住我想测试SSL,我相信mongrel不支持,什么是最好的开发服务器设置?


谢谢

最佳参考


部署一词可以有两种含义,具体取决于具体情况。您还混淆了Apache/Nginx的角色与其他组件的角色。


历史记录:本文最初写于2010年11月6日,当时Ruby应用服务器生态系统有限。我已于2013年3月15日更新了本文,其中包含生态系统中的所有最新更新。


免责声明:我是应用服务器之一Phusion Passenger的作者之一。


Apache vs Nginx



它们都是Web服务器。它们可以提供静态文件,但是 - 使用正确的模块 - 也可以提供动态Web应用程序,例如用PHP编写的应用程序.Apache更受欢迎,功能更多,Nginx更小更快,功能更少。


Apache和Nginx都不能提供开箱即用的Ruby Web应用程序,为此,您需要将Apache/Nginx与某种附加组件结合使用,稍后将对此进行介绍。


Apache和Nginx也可以充当反向代理,这意味着它们可以接收传入的HTTP请求并将其转发到另一个服务器,该服务器也会说HTTP。当该服务器响应HTTP响应时,Apache/Nginx会将响应转发回客户端;稍后您将了解为什么这是相关的。


Mongrel和其他生产应用服务器与WEBrick



Mongrel是一个Ruby应用程序服务器:具体而言,这意味着Mongrel是一个应用程序:



  1. 将Ruby应用程序加载到自己的进程空间中。

  2. 设置TCP套接字,允许它与外部世界(例如Internet)通信。
    Mongrel侦听此套接字上的HTTP请求,并将请求数据传递给Ruby Web应用程序。

  3. Ruby Web应用程序然后返回一个对象,该对象描述HTTP响应应该是什么样的,并且Mongrel负责将其转换为实际的HTTP响应(实际字节)并通过套接字将其发回。



然而,杂种已经相当过时了,现在它已不再维持。较新的替代应用程序服务器是:



  • Phusion Passenger

  • 独角兽


  • 彪马

  • Trinidad(仅限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

  • 可能无法直接暴露于互联网的应用服务器:Mongrel,Unicorn,Thin,Puma。这些应用服务器必须放在Apache和Nginx等反向代理Web服务器之后。

  • 我对Trinidad和TorqueBox不太了解,所以我省略了它们。



为什么必须将某些应用服务器置于反向代理之后?



  • 某些应用服务器每个进程只能同时处理1个请求。如果要同时处理2个请求,则需要运行多个app server实例,每个实例都提供相同的Ruby应用程序。这组app服务器进程称为 app server cluster (因此称为Mongrel Cluster,Thin Cluster等)。然后,您必须设置Apache或Nginx以反向代理到此群集。 Apache/Nginx将负责在集群中的实例之间分发请求(有关详细信息,请参阅I/O并发模型部分)。

  • Web服务器可以缓冲请求和响应,保护应用服务器免受慢客户端 - 非快速发送或接收数据的HTTP客户端。您不希望应用服务器在等待时无所事事客户端发送完整请求或接收完整响应,因为在此期间应用服务器可能无法执行任何其他操作。 Apache和Nginx非常擅长同时做很多事情,因为它们要么是多线程的,要么是偶数。

  • 大多数应用服务器都可以提供静态文件,但并不是特别擅长。 Apache和Nginx可以更快地完成它。

  • 人们通常会设置Apache/Nginx来直接提供静态文件,但是将不与静态文件对应的请求转发给应用服务器,这是一种很好的安全措施。 Apache和Nginx非常成熟,可以保护应用服务器免受(可能是恶意的)损坏的请求。



为什么某些应用服务器可以直接暴露给互联网?



  • Phusion Passenger与所有其他应用服务器完全不同。它的一个独特功能是它集成到Web服务器中。

  • Rainbows的作者公开表示将其直接暴露在互联网上是安全的。作者非常肯定HTTP解析器中没有漏洞(和类似的)。但是,作者没有提供任何保证,并说使用风险自负。



比较应用程序服务器



在本节中,我将比较我提到的大多数应用程序服务器,但不会比较Phusion Passenger。 Phusion Passenger和其他人一样是一个不同的野兽,我给它一个专门的部分。我也省略了Trinidad和TorqueBox,因为我不太了解它们,但是如果你使用JRuby它们只是相关的。



  • Mongrel 非常简陋。如前所述,Mongrel纯粹是单线程多进程,因此它仅在集群中有用。没有进程监视:如果群集中的进程崩溃(例如,由于应用程序中的错误),则需要手动重新启动。人们倾向于使用外部过程监控工具,如Monit和God。

  • Unicorn 是Mongrel的一个分支。它支持有限的进程监视:如果进程崩溃,它将由主进程自动重新启动。它可以使所有进程侦听单个共享套接字,而不是每个进程的单独套接字。这简化了反向代理配置。与Mongrel一样,它纯粹是单线程多进程。

  • 精简通过使用EventMachine库来使用事件I/O模型。除了使用Mongrel HTTP解析器之外,它不以任何方式基于Mongrel。它的集群模式没有进程监控,所以你需要监控崩溃等。没有类似Unicorn的共享套接字,所以每个进程都监听它自己的套接字。理论上,Thin的I/O模型允许高并发性,但在大多数实际使用Thin的情况下,一个Thin进程只能处理1个并发请求,因此您仍然需要一个集群。更多关于此部分中的这一特殊属性I/O并发模型。

  • Puma 也是来自Mongrel,但与Unicorn不同,Puma的设计纯粹是多线程的。因此,目前没有内置群集支持。您需要特别注意确保可以使用多个内核(有关详细信息,请参阅I/O并发模型一节)。

  • 彩虹通过使用不同的库支持多种并发模型。



Phusion Passenger



Phusion Passenger与其他所有人的工作方式截然不同。 Phusion Passenger直接集成到Apache或Nginx中,因此可以与Apache的mod_php进行比较。就像mod_php允许Apache为PHP应用程序提供服务一样神奇,Phusion Passenger允许Apache(以及Nginx!)几乎神奇地为Ruby应用程序提供服务。 Phusion Passenger的目标是让一切尽职尽责(tm)尽可能少的麻烦。[1]


不是为您的应用启动流程或集群,而是使用Phusion Passenger配置Apache/Nginx以提供静态文件和/或将代理请求反向代理请求:您只需:



  1. 您编辑Web服务器配置文件并指定Ruby应用程序的公共目录的位置。

  2. 没有第2步。



所有配置都在Web服务器配置文件中完成。 Phusion Passenger几乎可以自动化所有内容。无需启动集群和管理进程。启动/停止进程,在崩溃时重新启动它们等等 - 全部自动化。与其他应用服务器相比,Phusion Passenger的移动部件更少。这种易用性是人们使用Phusion Passenger的主要原因之一。


与其他应用程序服务器不同,Phusion Passenger主要使用C ++编写,速度非常快。


还有一个Phusion Passenger的企业版本具有更多功能,例如自动滚动重启,多线程支持,部署错误抵抗等等[2]


基于以上原因,Phusion Passenger是目前最受欢迎的Ruby应用服务器,为超过150,000个网站提供支持,包括纽约时报,皮克斯,Airbnb等大型网站。


Phusion Passenger与其他应用服务器



与其他应用服务器相比,Phusion Passenger提供了更多功能并提供了许多优势,例如:



  • 根据流量动态调整进程数。我们在资源受限的服务器上运行大量Rails应用程序,这些应用程序不面向公众,我们组织中的人员每天最多只使用几次。 Gitlab,Redmine等等.Phusion Passenger可以在不使用这些流程时将其拆除,并在使用时将其旋转,从而为更重要的应用程序提供更多资源。使用其他应用服务器,您的所有进程都会一直打开。

  • 根据设计,某些应用服务器并不擅长某些工作负载。例如,Unicorn仅用于快速运行请求:请参阅Unicorn网站部分在某些情况下更糟糕。



Unicorn不擅长的工作量是:[3]



  • 流式工作负载(例如Rails 4直播或Rails 4模板流)。

  • 应用程序执行HTTP API调用的工作负载。



Phusion Passenger Enterprise 4或更高版本中的混合I/O模型使其成为这类工作负载的绝佳选择。[4]



  • 其他应用服务器要求用户为每个应用运行至少一个实例。相比之下,Phusion Passenger在单个实例中支持多个应用程序。这大大降低了管理开销。

  • 自动用户切换,方便的安全功能。

  • Phusion Passenger支持许多MRI Ruby,JRuby和Rubinius。 Mongrel,Unicorn和Thin仅支持MRI。 Puma也支持所有3。

  • Phusion Passenger实际上支持的不仅仅是Ruby!它还支持Python WSGI,因此它也可以运行Django和Flask应用程序。事实上,Phusion Passenger正朝着成为多语言服务器的方向发展。 Node.js支持todo列表。

  • 带外垃圾收集。 Phusion Passenger可以在正常的请求/响应周期之外运行Ruby垃圾收集器,可能会将请求时间减少数百毫秒。 Unicorn也有类似的功能,但Phusion Passenger的版本更灵活,因为
    1)它不仅限于GC,可以用于任意工作。
    2)Phusion Passenger的版本适用于多线程应用程序,而Unicorn则不适用。

  • 自动滚动重启。在Unicorn和其他服务器上滚动重启需要一些脚本工作。 Phusion Passenger Enterprise为您完全自动化。



有更多的功能和优点,但列表真的很长。您应该参考综合Phusion Passenger手册(Apache版本,Nginx版本)或Phusion Passenger网站获取信息。[5] [6] [7]


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及更高版本实现。您可以轻松地在单线程多进程,纯多线程或甚至多个进程之间切换,每个进程都有多个线程。这个模型提供了两全其美的效果。

  • Evented。此模型与前面提到的模型完全不同。它允许非常高的I/O并发性,因此非常适合长时间运行的阻塞I/O工作负载。要利用它,需要来自应用程序和框架的明确支持。但是,像Rails和Sinatra这样的所有主要框架都不支持事件代码。这就是为什么在实践中,一个瘦进程仍然无法一次处理多个请求,使其有效地表现与单线程多进程模型相同。有一些专门的框架可以利用事件I/O,例如Cramp。



最近在Phusion博客上发布了一篇文章,关于根据您的工作负载优化调整进程和线程的数量。请参阅Tuning Phusion Passenger的并发设置。[8]


Capistrano的



Capistrano是完全不同的东西。在前面的所有部分中,部署是指在应用程序服务器中启动Ruby应用程序的行为,以便访问者可以访问它,但在此之前,通常需要做一些准备工作,例如:



  • 将Ruby应用程序的代码和文件上传到服务器计算机。

  • 安装应用所依赖的库。

  • 设置或迁移数据库。

  • 启动和停止您的应用可能依赖的任何守护进程,例如Sidekiq/Resque worker或其他任何守护进程。

  • 在设置应用程序时需要完成的任何其他事情。



在Capistrano的背景下,部署指的是做所有这些准备工作。 Capistrano不是应用程序服务器。相反,它是一个自动完成所有准备工作的工具。您告诉Capistrano您的服务器在哪里以及每次部署新版本的应用程序时都需要运行哪些命令,Capistrano将负责将Rails应用程序上传到服务器并运行您指定的命令。


Capistrano始终与应用程序服务器结合使用。它不会取代应用程序服务器。反之亦然,应用服务器不能取代Capistrano,它们可以与Capistrano结合使用。


当然你不能使用来使用Capistrano。如果你喜欢用FTP上传你的Ruby应用程序并且每次都手动运行相同的命令步骤,那么你可以这样做。其他人厌倦了它,所以他们在Capistrano自动化这些步骤。