Apache vs Nginx
他们都是web服务器,都能伺服静态文件。Apache更加流行,拥有更多的功能;Nginx则相对功能少、小巧、快速。
Apache 和 Nginx都能在盒子外(out-of-the-box)伺服Ruby服务器,为此你需要使用另外的插件来组合他们。
Apache 和 Nginx都能作为反向代理,就是说他们能够把进来的HTTP请求转发给其他服务器,接着把该服务器的响应转给客户端。
Mongrel以及其他production模式的服务器vs WEBrick
Mongrel是ruby实现的应用服务器,具体来说:
1,在自己的进程空间中加载Ruby app.
2, 创建一个TCP socket,允许它可以和外部世界(例如Internet)通信。Mongrel在这个socket上监听HTTP请求,并把请求数据转发给Ruby app。
3,Ruby app返回一个描述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 app 服务器,部分ruby部分C,主要是ruby,但它的HTTP 解析器为了性能是用C写的
- WEBrick比较慢且不够强壮,有普遍知道的内存泄漏问题,以及HTTP解析问题。
- 因为WEBrick是ruby默认自带的,所以WEBrick经常用于development模式下作为默认服务器,而其他服务器则需要另外安装。不建议在production模式下是用WEBrick服务器,虽然因为某些原因,Heroku选择了WEBrick作为默认服务器,他们以前是使用的Thin,但我不知道他们为什么换到了WEBrick
app服务器世界
- 当前所有的Ruby app 服务器都是http类型的,一些服务器直接将80端口暴露到internet中,另一些则没有
- 暴露80端口的:Phusion Passenger, Rainbows
- 没有直接暴露的:Mongrel, Unicorn, Thin, Puma. 这些服务器必须必须置于反向代理服务器之后,比如Apache and Nginx。
- 我不了解Trinidad and TorqueBox,,所以就忽略了
为什么有些服务器必须置于反向代理之后呢?
- 一些服务器的一个进程在同一时间只能处理一个请求,如果你想同时处理两个请求,你就需要启动多个服务器实例,都伺服同一个Ruby app。这种多进程app 服务器称为app服务器集群(比如Mongrel Cluster, Thin Cluster)。你必须启动Apache 或者 Nginx,给集群做反向代理,Apache/Nginx会处理好集群中不同应用实例间的分发工作。(更多内容参见章节 "I/O并发模型").
- web 服务器可以缓存请求和响应。有些客户端的发送数据、接收数据的速度缓慢,web服务器可以隔离app server和慢客户端。你当然不希望app server 在等待客户端收发数据时什么也不干。Apache 和 Nginx 擅长同时很多事情,因为他们是多线程或者基于事件的。
- 大多数的app server可以伺服静态文件,但不是很擅长。Apache 和 Nginx的速度更快。
- 人们经常直接使用 Apache 或者 Nginx伺服静态文件,而不会处理前向请求( forward requests ),这是比较安全的策略。 Apache 和Nginx足够聪明,可以保护app server远离恶意请求。
为什么有些服务器可以直接暴露在Internet中?
- Phusion Passenger和其他app server不一样,其中一个比较特点是可以融入其他服务器。
- Rainbows的作者公开指出,Rainbows可以直接暴露在internet中。他十分不会在解析HTTP过程中遭受攻击。still, the author provides no warranty and says that usage is at own risk.
Application 服务器对比
在这一章中,我会比较我提到的大多数服务器,但不包括Phusion Passenger。Phusion Passenger和其他的不一样,我会单独开出一章。我还会忽略Trinidad 和 TorqueBox,因为我对他们不是很了解。只有你用到JRuby的时候才会涉及到他们。
- Mongrel 是块暴露的石头。像之前提到的,Mongrel仅仅是单线程、多进程,所以它只用于集群(cluster)中。没有进程监控,意味着如果集群中一个进程崩溃了,则需要手动重启。人们需要使用额外的进程来照看Mongrel,比如Monit 和 God。
- Unicorn 是从Mongrel中fork出来的。支持监控一定数量的的进程:如果一个进程崩溃了,则会被主进程自动重启。它能让所有进程都监听同一个共享的socket,而不是每个进程独自使用单独的socket。这会简化反向代理的配置。像Mongrel一样,也是单线程、多进程。
- Thin 利用EventMachine库,实现基于事件的 I/O model。它并不是使用Mongrel的HTTP解析器,没有基于Mongrel。它的集群节点没有进程监控,所以你需要去监控进程是否崩溃。每个进程监听独自的socket,不像Unicorn一样共享socket。理论上来说,Thin的I/O模式允许高并发,这也是Thin被应用的大部分场合。一个Thin的进程只能处理一个并发请求,所以你还需要集群。关于这个古怪的性质,更多内容参见“I/O并发模型”。
- Puma 也是从Mongrel中fork出来的,但和Unicorn不一样的是,Puma被设计成多进程的。目前不支持集群。你需要特别确认的是你能实现多核( You need to take special care to ensure that you can utilize multiple cores )。 更多内容参见“I/O并发模型”。
- Rainbows 通过给不同的库实现多种并发模型 。
I/O并发模型
- 单线程,多进程。 Ruby app Server中比较常见、流行的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。