Phusion Passenger/mod_rails令Rails部署变得更容易

PhusionPassenger/mod_rails令Rails部署变得更容易

一个旨在从Apache网页服务器上更便捷的部署RubyonRails的新项目诞生了。PhusionPassenger/mod_rails似乎已经实现了这个目标,并得到了Rails官方和很多人的推荐。我们采访了PhusionPassenger的创建者之一,NinhBui,想了解一下项目背后的故事和它未来的发展方向。

首先,我们想弄清楚名字的问题──这个项目的网站是modrails.com,但是名字却起为PhusionPassenger。NinhBui是这么解释的:

Phusion是我们公司的名字,然而PhusionPassenger是mod_rails官方的名称。大多数社区的朋友都会从mod_rails这个名字中了解它的用途,因为它的命名方式为传统的mod_*,所以我们由此保留了这个别名。

尽管起初我们打算就只叫它mod_rails,但是RubyonRails核心团队和我们都认为“Passenger”(乘客)要比用一个Rails词汇更贴切。特别是,我们想让PhusionPassenger(也就是mod_rails)为用户带来的体验与(火车)乘客是一致的:只要坐在那里,便可享受乘坐的乐趣;-)。

另一个问题是关于PhusionPassenger所发放的许可:

对于许可来说,我们使用的是GPLv2,并附加了一个额外的条款。大家通常都会对许可产生误解,也正好趁此机会把这些问题一并加以解释:我们实际上已经允许社区对源代码做更广泛的应用,而不是限制这个许可。

同样,我们有很多在开源社区工作的经验,我们是与它一起成长的。我们相信,将开源的开发模式与商业公司的驱动结合起来,会令我们提供更好的产品。换句话说,我们认为,对于商业机构来说,这是一种回馈社区最好的方式。

拿PhusionPassenger为例,它的设计和开发是为了追求产品环境(productionenvironments)下的稳定与高效。然而,可能会有人在部署的时候遇到问题,或者需要某些特定的功能。我们会为这些人提供付费的商业技术支持。我们团队的技术专家在各个领域都有着丰富的经验──特别是基于Linux的环境下──并且对Ruby的内在机理、RubyonRails和Passenger都很熟悉。

我们都很好奇,PhusionPassenger在应对Rails部署中类似的解决方案时是如何进行叠加的:

与Swifiply、MongrelCluster等不同,PhusionPassenger的应用池(applicationpool)是在当前流量的基础上进行自动管理的。还有就是,如果Rails应用程序崩溃了,它会自动重启。这意味着,配置或者进程监控都是多余的,而且这会削减系统管理的成本。有很多种配置选项是可用的,它们都被记录在用户指南中了。

我们感兴趣的是,究竟如何用PhusionPassenger去部署和重新部署Rails应用程序。

只要花费你两分钟的时间,不过这要看你的网速如何了;-)。开个玩笑。用PhusionPassenger更新并且重新部署你的Rails应用程序只需再上传一次应用程序,并调用restart.txt。要做的,就这么多。如果你想重新启动Apache(我认为大多数人可能都想这么做;-)),就必须做第二步。

从技术角度来讲,第二步是用来更新restart.txt文件中时间戳的,PhusionPassenger会根据那个时间戳决定是否重启你的Rails应用程序。

Rails部署并不是Phusion开发者试图解决的唯一的问题。当运行很多Rails进程时,内存占用过多也是一个问题。每个Ruby进程都必须把Ruby和Rails函数库载入到内存中──因为这些是不同的进程,此时它是没有被共享的(Ruby代码是储存在堆栈中的,所以不像共享的函数库,在不同进程中是无法共享的)。

Phusion的一位开发人员,HongliLai试图通过Unix系统函数fork()让Ruby不同进程之间共享数据。它的核心思想是首先获取一个设置好函数库的Ruby进程,然后通过fork()让进程去获取其他的进程。在进程中调用fork(),可以说是一种非常有效复制进程的方式。这两个进程基本上是一样的,在它们的地址空间中包含有相同的数据。但是,这不是共享内存,而是系统的虚拟内存,操作系统调用了一个名为CopyOnWrite(写时复制,简写成COW)的方法让不同进程可以读取相同的数据,但是却没有修改它们私有的拷贝。只要数据是只读的,那么有一份数据就够用了。不过,一旦进程开始对数据进行了修改,数据的拷贝就只能归属于这个进程了。很明显,共享只读数据(例如函数库代码或其他类似的)是一种非常可行的方法。

然而,对于使用垃圾回收的编程语言来说,存在一个问题:完整的垃圾回收会遍历堆栈,并将所有遍历到的对象作标记。这里面很重要的一个词是“作标记”──在对象上插上一面旗。如果这些对象中的任何一个被其他进程(通过fork())共享了,COW便会起作用,并将数据拷贝过来──这意味者数据不会再被共享,所有进程都拥有它自己的拷贝。

HongliLai针对这个问题的解决方案是令Ruby的垃圾回收器COW的更友好,也就是说,回收的时候不会再引起数据的拷贝。Ninh对这个问题和它与Phusion产品之间的关联进行了详细的阐述:

COW垃圾回收器已经基本上完成了。我们现在正准备发布并建立它的官网。而且,我们还在屯特大学(UniversityofTwente)的ir.HansScholten帮助下撰写了一篇相关的论文。未来几周内,我们就会发布一个版本。我们理解大家可能不太喜欢为Ruby打补丁,所以我们付出很多额外的努力来确保安装尽可能的简单,而且要完全独立,不要涉及任何的系统文件。

我们会把它同“Ruby企业版”(是的,我们很清楚这个名字,但是请允许我们在Railsconf上对它作详细说明;-))一起发布。恳请大家对我们有一些耐心,我们向你保证,那将是非常值得关注的东西。还有一点要注意的是,Ruby企业版是完全与标准Ruby版(1.8)向后兼容的。

如果PhusionPassenger被应用到Ruby企业版上,那么Passenger会自动使用COW语义。这可令Rails应用程序大幅节省使用的内存。实际上,先前的测试已经表明平均会节省33%的内存使用量。

认真的读者将会注意到,Ruby企业版是以一种透明的方式完成这些工作的,而且同样为程序开发者提供了在运行时打开和关闭GC优化的功能。因为这个原因,Ruby企业版应当算作Ruby的一个超集(superset)。

由此,我们不得不改变Ruby堆栈的执行方式。它现在使用了一组作了标记的位阈(bitfield),而不是在对象中对二进制位(bit)进行标记。它的性能有些不确定,这要取决于应用程序和工作量的大小。在一些Rails应用程序中,我们进行了测试,有的提高了5%,有的提高了20%,有的则是0%,也就是说,性能没有变化。如果您想了解更多的相关内容,我们会在Railsconf上对这个现象作详细的阐述,或者日程上允许的话,可能会提前给大家讲讲。

如果大家想试用一下PhusionPassenger,Phusion网站上提供了一个基础视频教程,或者直接查看安装文档。PhusionPassenger是一个开源项目,你可以到PhusionPassenger的GitHub的repository中获取源代码。

相关推荐