Capistrano、Passenger和Nginx - 它们如何共同工作?

12 浏览
0 Comments

Capistrano、Passenger和Nginx - 它们如何共同工作?

输出内容缺失

admin 更改状态以发布 2023年5月22日
0
0 Comments

“Deployment”这个词根据上下文的不同有两个意思。同时,你也混淆了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套接字,允许它与外部世界(例如互联网)进行通信。Mongrel在此套接字上监听HTTP请求并将请求数据传递给Ruby Web应用程序。
  3. Ruby Web应用程序然后返回一个对象,该对象描述了HTTP响应的实际外观,而Mongrel负责将其转换为实际的HTTP响应(实际字节)并通过套接字发送回。

然而Mongrel相当过时,现在不再维护。较新的替代应用程序服务器是:

  • Phusion Passenger
  • 独角兽
  • Thin
  • Puma
  • 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号端口的互联网上,而另一些可能不会。

  • 可以直接暴露在互联网上的应用服务器:Phusion Passenger、Rainbows
  • 可能无法直接暴露在互联网上的应用服务器:Mongrel、Unicorn、Thin、Puma。这些应用服务器必须放在反向代理服务器(如Apache和Nginx)后面。
  • 我对Trinidad和TorqueBox了解不够,所以我省略了它们。

为什么有些应用服务器必须放在反向代理后面?

  • 有些应用服务器每个进程只能同时处理一个请求。如果您想同时处理两个请求,您需要运行多个相同的应用服务器实例来为Ruby应用程序提供服务。这组应用程序服务器进程称为应用程序服务器集群(因此称为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一样,它纯粹是单线程多进程的。
  • Thin使用事件驱动的I/O模型,利用EventMachine库。除使用Mongrel HTTP解析器外,它与Mongrel毫不相干。其群集模式没有进程监控,因此您需要监控崩溃等。没有像Unicorn那样的共享套接字,因此每个进程都监听自己的套接字。理论上,Thin的I/O模型允许高并发,但在大多数实际使用Thin时,一个Thin进程只能处理一个并发请求,因此仍然需要一个集群。关于这种特殊属性的更多信息,请参见"I/O并发模型"部分。
  • Puma也是从Mongrel分支而来,但与Unicorn不同,Puma旨在纯粹地支持多线程。因此,目前没有内置的集群支持。您需要特别注意以确保可以利用多个内核(有关更多信息,请参见"I/O并发模型"部分)。
  • Rainbows通过使用不同的库支持多个并发模型。

Phusion Passenger

Phusion Passenger与所有其他应用服务器的工作方式都非常不同。Phusion Passenger直接集成到Apache或Nginx中,因此可以与Apache的mod_php相比。就像mod_php允许Apache服务PHP应用程序一样,几乎是神奇的,Phusion Passenger允许Apache(以及Nginx!)服务Ruby应用程序,几乎是神奇的。Phusion Passenger的目标是尽可能少地麻烦地让所有事情正常工作。

使用Phusion Passenger,您无需启动进程或集群,也无需配置Apache / Nginx来提供静态文件并/或将请求反向代理到进程/集群。您只需要做以下两步:

1.编辑Web服务器配置文件并指定您的Ruby应用程序的“public”目录的位置。
2.没有第二步。

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

另外,与其他应用程序服务器不同,Phusion Passenger主要是用C++编写的,因此非常快。

Phusion Passenger还有一个“企业版”,具有更多功能,例如自动滚动重新启动,多线程支持,防止部署错误等等。

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

与其他应用程序服务器相比,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。Puma也支持3种。

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

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

-自动滚动重新启动。在独角兽和其他服务器上进行滚动重启需要一些脚本工作。 Phusion Passenger Enterprise完全为您自动化此方式。

还有更多功能和优势,但列表真的很长。您应参考全面的Phusion Passenger手册(Apache版本,Nginx版本)或Phusion Passenger网站获取信息。

输入/输出并发模型

  • 单线程多进程。 传统上,这是Ruby应用服务器中最流行的I/O模型,部分原因是在Ruby生态系统中,多线程支持非常糟糕。每个进程一次只能处理一个请求。Web服务器在进程之间负载均衡。该模型非常健壮,程序员很难引入并发错误。然而,它的I/O并发性非常有限(受进程数量限制)。该模型非常适用于快速的、短时间运行的工作负载,但对于慢速的、长时间运行的阻塞I/O工作负载,例如调用HTTP API的工作负载,非常不适合。
  • 纯多线程。如今,Ruby生态系统具有出色的多线程支持,因此这种I/O模型变得非常可行。多线程允许高I/O并发性,使其适用于短时间和长时间阻塞I/O工作负载。程序员更可能引入并发错误,但幸运的是,大多数Web框架的设计方式使得这种情况非常不可能发生。但是需要注意的是,即使有多个线程,MRI Ruby解释器由于使用全局解释器锁(GIL)不能利用多个CPU核心。您可以通过使用多个多线程进程来解决此问题,因为每个进程都可以利用一个CPU核心。JRuby和Rubinius没有GIL,因此可以完全利用单个进程中的多个核心。
  • 混合多线程多进程。主要由Phusion Passenger Enterprise 4及更高版本实现。您可以轻松切换到单线程多进程、纯多线程或可能是每个进程都有多个线程的多进程。这个模型融合了两者的优点。
  • 事件驱动。这种模型与前面提到的模型完全不同。它允许非常高的I/O并发性,因此非常适用于长时间运行的阻塞I/O工作负载。要利用它,需要应用程序和框架的显式支持。但是,所有主要框架如Rails和Sinatra都不支持事件驱动代码。这就是为什么在实践中,Thin进程仍然无法同时处理超过1个请求,使其的行为与单线程多进程模型相同。有一些专门的框架可以利用事件驱动I/O,例如Cramp。

Phusion博客最近发布了一篇关于如何根据您的工作负载最优调整进程和线程数量的文章。请参见Tuning Phusion Passenger's concurrency settings

Capistrano

Capistrano与前面的所有部分都不同。在所有前面的部分中,“部署”是指在应用服务器中启动您的Ruby应用程序,以便访问者可以访问,但在这之前,通常需要进行一些准备工作,例如:

  • 将Ruby应用程序的代码和文件上传到服务器机器中。
  • 安装应用程序依赖的库。
  • 设置或迁移数据库。
  • 启动和停止应用程序可能依赖的任何守护程序,如Sidekiq/Resque workers或其他。
  • 在设置应用程序时需要完成的任何其他事情。

在Capistrano的上下文中,“部署”是指完成所有这些准备工作。Capistrano不是应用程序服务器,它是自动化所有准备工作的工具。您告诉Capistrano您的服务器在哪里以及每次部署新版本应用程序时需要运行哪些命令,Capistrano会为您上传Rails应用程序到服务器并运行您指定的命令。

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

当然,您不一定要使用Capistrano。如果您更喜欢通过FTP上传Ruby应用程序并手动运行相同的命令步骤,则可以这样做。其他人感到厌倦了,所以他们在Capistrano中自动化了这些步骤。

0