Ruby 服务器对比
Posted Ruby那些事
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ruby 服务器对比相关的知识,希望对你有一定的参考价值。
The word "deployment" can have two meanings depending on the context. You are also confusing the roles of Apache/nginx with the roles of other components.
Historic note: This article was originally written on November 6, 2010, when the Ruby app server ecosystem was limited. I've updated this article on March 15 2013 with all the latest updates in the ecosystem.
Disclaimer: I am one of the authors of Phusion Passenger, one of the app servers.
一,Apache vs Nginx
他们都是web服务器,都能伺服静态文件,利用恰当的模块也能伺服动态的web应用。Apache更加流行,拥有更多的功能;Nginx则相对小巧、快速、功能少。
让Apache 和 Nginx 来伺服 Ruby 服务器都不是开箱即用(out-of-the-box)的,为此你需要使用另外的插件来组合他们。
Apache 和 Nginx都能作为反向代理,就是说他们能够把进来的 HTTP 请求发给其他服务器,接着把该服务器的 HTTP 响应转给客户端,后面会看到为什么和这个有关系。
二,Mongrel以及其他production环境的服务器 vs WEBrick
Mongrel是Ruby实现的应用服务器,具体来说:
1,在自己的进程空间中加载 Ruby 应用。
2, 创建一个 TCP socket,允许它可以和外部世界通信(例如Internet)。Mongrel 在这个socket上监听 HTTP 请求,并把请求数据转发给 Ruby 应用。
3,Ruby 应用返回一个描述 HTTP 响应的对象,Mongrel 将其转换为真正的 HTTP 响应字节,并发回到 socket 中。
然而 Mongrel 已经不再维护了,其他替代的服务器是:
Phusion Passenger
Unicorn
Thin
Puma
Trinidad (JRuby only)
TorqueBox (JRuby only)
接下来我会讲一讲他们和 Mongrel 的区别
WEBrick 和 Mongrel 很像,区别如下:
WEBrick 不适合用于 production。WEBrick 完全是用 Ruby 写的;Mongrel( 以及其他 Ruby 应用服务器)是部分 Ruby 部分C,主要是 Ruby,但它的 HTTP 解析器为了性能是用 C 写的。
WEBrick 速度比较慢而且不够强壮,有普遍知道的内存泄漏问题,以及 HTTP 解析问题。
因为 WEBrick 是 Ruby 默认自带的,所以 WEBrick 经常用于 development 环境下作为默认服务器,而其他的服务器则需要另外安装。不建议在production 环境下使用 WEBrick 服务器,虽然因为某些原因,Heroku 选择了WEBrick 作为默认服务器,他们以前使用的是 Thin,但我不知道他们为什么换到了 WEBrick。
三,应用服务器世界
当前所有的Ruby 应用服务器都是 HTTP 类型的,一些服务器直接将80端口暴露到 Internet 中,另一些则没有。
暴露80端口的:Phusion Passenger, Rainbows。
没有直接暴露的:Mongrel, Unicorn, Thin, Puma。这些服务器必须必须置于反向代理服务器之后,比如Apache 和 Nginx。
我不了解 Trinidad 和 TorqueBox,所以就忽略了。
为什么有些服务器需要置于反向代理之后?
某些服务器的每个进程在同一时间只能处理一个请求,如果想同时处理两个请求,你就需要启动多个服务器实例,都伺服同一个 Ruby 应用。这种应用服务器进程的集合称为应用服务器集群(比如Mongrel Cluster, Thin Cluster)。然后你必须启动 Apache 或者 Nginx,给集群做反向代理,Apache/Nginx 会处理好集群中不同应用实例间的请求分发。(更多内容参见章节 "I/O并发模型”)
Web 服务器可以缓存请求和响应。有些客户端发送数据、接收数据的速度缓慢,你当然不希望应用服务器在等待客户端收发数据时什么也不干,Web 服务器可以隔离应用服务器和慢客户端。Apache 和 Nginx 擅长同时很多事情,因为他们是多线程或者基于事件的。
大多数的应用服务器可以伺服静态文件,但不擅长,而Apache 和 Nginx可以更快速度处理这件事情。
人们经常直接使用Apache 或者 Nginx伺服静态文件,而不会处理需要转发的请求(forward requests),这是比较安全的策略。Apache 和Nginx足够聪明,可以保护应用服务器远离恶意请求。
为什么有些服务器可以直接暴露在Internet中?
Phusion Passenger 和其他应用服务器不一样,其中一个特点是可以融入其他服务器。
Rainbows 的作者公开指出,Rainbows 可以直接暴露在 Internet 中。他非常确认在解析 HTTP 过程中不会轻易遭受攻击。still, the author provides no warranty and says that usage is at own risk.
四,应用服务器对比
在这一章中,我会比较我提过的大多数服务器,但不包括 Phusion Passenger。Phusion Passenger 和其他的不一样,我会单独开出一章。我还会忽略 Trinidad 和 TorqueBox,因为我对他们不是很了解,只有你用到 JRuby 的时候才会涉及到他们。
Mongrel 是块暴露的石头。像之前提到的,Mongrel 仅仅是单线程、多进程,所以它只用于集群(cluster)中。没有进程监控,意味着如果集群中一个进程崩溃了,则需要手动重启。人们需要使用额外的进程来照看 Mongrel,比如 Monit 和 God。
Unicorn 是从 Mongrel 中fork出来的。支持监控一定数量的的进程:如果一个进程崩溃了,则会被主进程自动重启。它能让所有进程都监听同一个共享的socket,而不是每个进程使用单独的socket,这会简化反向代理的配置。像Mongrel一样,Unicorn 是单线程、多进程。
Thin 利用 EventMachine 库,实现基于事件的 I/O 模型。它并不是使用 Mongrel 的 HTTP 解析器,没有基于 Mongrel。它的集群节点没有进程监控,所以你需要去监控进程是否崩溃。每个进程监听各自的socket,不像 Unicorn 一样共享socket。理论上来说,Thin 的I/O 模型允许高并发,这也是 Thin 被应用的大部分场合。一个 Thin 的进程只能处理一个并发请求,所以你还需要集群。关于这个古怪的性质,更多内容参见“I/O并发模型”。
Puma 也是从 Mongrel 中fork出来的,但和 Unicorn 不一样的是,Puma 是基于多线程,使用 Thread Pool 实现。因为 GIL 的存在,所以 MRI 不能利用多核实现CPU并行,所以你需要特别确认的是你能利用多核。更多内容参见“I/O并发模型”。
Rainbows 通过给不同的库实现多种并发模型 。
五,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文件夹的路径
没有第二步。
所有的配置工作都在Web 服务器配置文件的指导下做完了,Phusion Passenger几乎自动化了所有事情,不需要启动集群以及管理进程。启动或者停止进程,他们崩溃时重启,这些都被自动化了。和其他应用服务器相比,Phusion Passenger 所需要做的改动工作非常少,这是人们使用 Phusion Passenger 的主要原因。
和其他应用服务器不同的是,Phusion Passenger 主要是用 C++ 写的,速度很快。
Phusion Passenger 的企业版有更多的特性,比如自动回滚重启,支持多线程,容错部署。(such as automated rolling restarts, multithreading support, deployment error resistance, etc.)
基于以上原因,Phusion Passenger是当前最流行的 Ruby 应用服务器,服务于超过50,000 站点,包括大型站点:New York Times, Pixar, Airbnb。
六,Phusion Passenger vs 其他服务器
相对其他的服务器 ,Phusion Passenger 提供了更多的特性功能:
根据访问量自动调整进程的数量。在资源有限的服务器上,我们运行多个 Ruby 应用,而我们的应用不对外公开,而且组织内的访客每天的访问量也很低,例如 Gitlab, Redmine等。Phusion Passenger 能够在进程不使用的时候挂起他们,需要的时候恢复进程,为更重要的应用腾出资源。相比之下,其他的服务器的所有进程会一直运行着。
有些服务器不适合某些特定的负荷。例如 Unicorn 为轻量快速的请求而设计,See the Unicorn website section "Just Worse in Some Cases".
Unicorn 不擅长的负荷:
> 流(e.g. Rails 4 live streaming or Rails 4 template streaming)
> 调用 HTTP API
Phusion Passenger Enterprise 4及后续版本中多种I/O模型,使它非常适合这种负荷。
其他的应用服务器需要用户为每个应用至少启动一个实例,相比之下,Phusion Passenger 支持一个实例多个应用。这大大减少管理员的开支。
Phusion Passenger 支持多个 MRI Ruby, JRuby 和 Rubinius。Mongrel, Unicorn 和 Thin 只支持 MRI,Puma也支持三个。
Phusion Passenger 不仅支持 Ruby,它还支持 Python WSGI,所以同样能运行 Django 和 Flask 应用。实际上,Phusion Passenger正在向多语言服务器发展的道路上前进,Node.js的支持已经列在计划中。
Out-of-band garbage collection。Phusion Passenger 可以在请求的循坏外执行 Ruby 的垃圾回收,可以潜在地减少几百毫秒的请求时间(reducing request times by hundreds of milliseconds)。Unicorn也有类似的功能,但是Phusion Passenger 的版本更加灵活,因为 1,it's not limited to GC and can be used for arbitrary work。2,Phusion Passenger的版本适应多进程应用,而 Unicorn 则不行。
自动回滚重启(Automated rolling restarts)。Unicorn 以及其他应用服务器的回滚重启需要脚本来执行,Phusion Passenger 企业版自动帮你完成了。
还有更多的特性和优势,暂不一一列举。你可以参考全面的 Phusion Passenger 手册( Apache version, Nginx version),或者到官网得到更多信息。
七,I/O并发模型
单线程,多进程。 Ruby 应用服务器中比较常见、流行的 I/O 模型,主要是因为 Ruby 生态系统中的多线程支持比较差。一个进程同时仅且只能处理一个请求,web 服务器通过多进程来进行均衡负载。这种模型比较稳定,开发者不会轻易造成并发bug。这种模型适合执行快速的短请求,不适合速度慢、长请求阻塞I/O的运算,例如 调用HTTP API。
纯多线程 。现在Ruby生态系统已经很支持多线程了,所以这种I/O模型变得切实可行。多线程支持高I/O并发,既适合短请求也适合长请求。开发者也很容易引入并发bug,幸运的是大多数框架按照这种方式设计,所以也不太可能发生。有一个需要注意的事情是,因为使用了全局解释器锁(GIL),MRI Ruby 解释器不能均衡使用多个CPU内核,即使有多个线程。为此,你可以使用多个进程,每个进程使用一个CPU内核。JRuby 和 Rubinius没有GIL,所以他们的一个进程可以均衡负载多个CPU内核 。
结合多线程、多进程 。Phusion Passenger Enterprise 4以后版本实现了。你可以轻易在以下模型切换:单进程多线程,纯多线程,多进程多线程。这种模型给出了最好的选择方式。
事件。这种模型和之前提到的模型不一样。它允许极高的I/O并发,以及非常适合长请求。为实现此功能,需要从应用到框架的详细支持。然而主要的框架(Rails 和 Sinatra)并不支持事件模型。这也是实际上一个Thin进程同时不能处理多个请求的原因,就像单线程多进程模型一样。只有专门的框架才充分利用事件I/O模型,例如Cramp。
八,Capistrano
Capistrano和其他的不一样。在之前的所有章节中,“部署”指的是在服务器上启动 Ruby 应用,然后对访客开放,但是在这之前需要一些准备工作,例如:
将 Ruby 应用的代码和文件上传到服务器机器上。
安装应用所依赖的库。
创建或者迁移数据库。
启动或者停止应用依赖的守护进程,例如 Sidekiq/Resque 或者 whatever。
启动应用时需要做的所有其他事情。
在 Capistrano 的语义中,“部署”意味着去做所有的准备工作。Capistrano 不是一个服务器,反而是一个自动做那些准备工作的工具。你告诉 Capistrano 你的服务器在哪里,以及每当你部署新版本应用的时候需要执行的命令,Capistrano 就能帮你上传 Ruby 应用到服务器上并且运行你指定的命令。
Capistrano 总是与应用服务器组合使用,并不会替代应用服务器。反之亦然,应用服务器也不会替代 Capistrano。
当然 Capistrano 也不是必须使用的。如果你可以使用 FTP 或者 手动上传 Ruby 应用,每一次都执行相同的动作。其他人厌倦这种重复,所以他们在 Capistrano 中自动执行这些步骤。
以上是关于Ruby 服务器对比的主要内容,如果未能解决你的问题,请参考以下文章