这个答案是对其他答案的补充,并解释了为什么 Unicorn 在它前面需要 nginx。
TL;DR Unicorn 通常与像 nginx 这样的反向代理一起部署的原因是它的创建者故意这样设计它,为了简单而做出权衡。
首先,没有什么可以阻止您在没有反向代理的情况下部署 Unicorn。但是,这不是一个好主意。让我们看看为什么。
Unicorn 遵循 Unix 哲学,即做好一件事,即为快速、低延迟的客户提供服务(我们将看看这意味着稍后)。 Unicorn 是为快速、低延迟的客户端设计的这一事实也意味着它不太适合慢、高延迟的客户端,这确实是事实。这是 Unicorn 的弱点之一,也是反向代理发挥作用的地方:它位于 Unicorn 前面,负责处理那些慢客户端(我们将看到如何稍后)。
幸运的是,这样的反向代理已经存在,名为nginx。
只处理快速客户端的决定大大简化了 Unicorn 的设计,并允许更简单和更小的代码库,但代价是增加了部署部门的复杂性(即,除了 Unicorn 之外,您还必须部署 nginx )。
另一种选择是设计 Unicorn,使其不需要反向代理。然而,这意味着它必须实现额外的功能来完成现在 nginx 所做的所有事情,从而导致更复杂的代码库和更多的工程工作。
相反,它的创建者决定利用经过实战考验且设计精良的现有软件,避免将时间和精力浪费在其他软件已经解决的问题上。
但是,让我们获得技术并回答您的问题:
为什么Unicorn需要和nginx一起部署?
以下是一些关键原因:
Unicorn 为客户端使用阻塞 I/O
依赖反向代理意味着 Unicorn 不需要 使用非阻塞 I/O。相反,它可以使用阻塞 I/O,这本质上更简单,程序员也更容易遵循。
正如DESIGN 文档所述:
[使用阻塞 I/O] 允许在 Ruby 解释器中遵循更简单的代码路径并减少系统调用。
不过,这也有一些后果:
关键点 #1:独角兽对慢速客户端效率不高
(为简单起见,我们假设设置有 1 个独角兽工人)
由于使用了阻塞 I/O,Unicorn worker 一次只能为一个客户端提供服务,因此慢速客户端(即连接速度慢的客户端)会有效地让 worker 忙于更长的时间(比快速客户端会做的)。与此同时,其他客户端只会等到 worker 再次空闲(即请求会堆积在队列中)。
为了解决这个问题,在 Unicorn 前面部署了一个反向代理,它完全缓冲传入的请求和应用程序响应,然后发送它们中的每一个一次(又名勺子喂他们)分别给独角兽和客户。在这方面,您可以说反向代理“屏蔽”了 Unicorn 免受慢速网络客户端的影响。
幸运的是,Nginx 是这个角色的绝佳人选,因为它旨在高效地处理数千个并发客户端。
至关重要的是,反向代理应与 Unicorn 位于同一本地网络中(通常位于通过 Unix 域套接字与 Unicorn 通信的同一物理机器中),以便将网络延迟保持在最低限度。
因此,这样的代理有效地扮演了 Unicorn 最初设计为服务的 快速客户端 的角色,因为它代理对 Unicorn fast 的请求并保持工作人员忙于尽可能短的时间(与连接速度较慢的客户端所需的时间相比)。
关键点#2:Unicorn 不支持 HTTP/1.1 keep-alive
由于 Unicorn 使用阻塞 I/O,这也意味着它无法支持 HTTP/1.1 的 keep-alive 功能,因为慢速客户端的持久连接会很快占用所有可用的 Unicorn worker。
因此,为了利用 HTTP 保持活动,猜猜看:使用了反向代理。
另一方面,nginx 只需几个线程就可以处理数千个并发连接。因此,它没有像 Unicorn 这样的服务器的并发限制(基本上限制了工作进程的数量),这意味着它可以很好地处理持久连接。可以在here 找到更多实际工作原理。
这就是为什么 nginx 接受来自客户端的 keep-alive 连接,并通过通常通过 Unix 套接字的普通连接将它们代理到 Unicorn。
第 3 点:Unicorn 不太擅长提供静态文件
再次重申,提供静态文件是 Unicorn可以 做的事情,但设计目的不是为了高效。
另一方面,像 nginx 这样的反向代理虽然在这方面做得更好(即sendfile(2) 和缓存)。
更多
PHILOSOPHY 文档中概述了其他要点(请参阅“通过反向代理提高性能”)。
另见nginx's basic features。
我们看到,通过利用现有软件(即 nginx)并遵循“做一件事,做好”的 Unix 理念,Unicorn 能够遵循更简单的设计和实现,同时保持高效地为 Rack 应用程序提供服务(例如,您的 Rails 应用程序)。
有关更多信息,请参阅 Unicorn 的 philosophy 和 design 文档,其中更详细地解释了 Unicorn 设计背后的选择以及为什么 nginx 被认为是 Unicorn 的良好反向代理。