Don't Repeat Yourself (DRY)。此原则要求应用程序的行为定义在授权位置,并且不能在应用程序的其他地方重复。DRY 将极大地增强应用程序的可维护性,因为它最大限度地减少了变更程序代码时所需的编辑工作。
Rails 是一个 Ruby gem,您可以使用以下命令将它安装在 JRuby 环境中:
jruby -S gem install rails --include-dependencies
|
此命令将在 JRuby 安装目录中安装最新版本的 Rails,并包括所有合适的依赖关系。-S 开关表示 rails 脚本位于 JRuby 的 bin 目录中。JRuby 1.1 将默认包括各种依赖关系,因此该版本不需要 --include-dependencies 开关。
您也可以安装较早版本的 Rails。举例来说,以下命令将安装 Rails 1.2.6:
jruby -S gem install rails -version 1.2.6 --include-dependencies
|
除了 Ruby-on-Rails 框架和 JRuby 解释程序之外,部署应用程序还需要一个 Web 服务器和一个数据库。本文首先将概述部署 Ruby-on-Rails 应用程序的传统方法。传统 一词可以表示最近的技术。然后,本文将探研使用 GlassFish 应用服务器的替代方案。
传统的 Rails 部署
传统 Ruby-on-Rails 部署中的软件
WEBrick 是使用 Ruby 编写的一个开源 HTTP 服务器库。WEBrick 是标准 Ruby 库的一部分,它用于在部署环境中测试 Ruby-on-Rails 应用程序。
Mongrel 是一个便捷的 HTTP 库,并且作为针对 Ruby 的 Web 服务器,它可以在生产环境中托管 Ruby Web 应用程序。可以将 Mongrel 作为 Ruby gem 安装。
Capistrano 是使用 Ruby 编写的一款工具,用于自动化 Rails 应用程序的部署。须将 Capistrano 作为 Ruby gem 安装。
Apache HTTPD 是一个开源模块,它包含流行的 Apache HTTP 服务器。
nginx 是一个轻量级的 Web 服务器和反向代理。
LightTPD 是针对速度关键型环境优化过的一个 Web 服务器。
|
|
Rails 应用程序的传统部署环境在前台包括一个轻量级 Web 服务器,如 Apache HTTPD、nginx 或 LightTPD。它借助 Mongrel Web 服务器集群,并使用基于 HTTP 的反向代理进行配置。Mongrel Web 服务器集群的非正式说法是 "pack of Mongrels"。
静态内容由 Web 服务器提供,而动态内容则通过集群中的 Mongrel Web 服务器代理。Rails(以及各个 Mongrel Web 服务器)是单线程的,并且一次只能处理一个请求。因此,所需的 Mongrel 实例数量直接与待处理的并发请求成比例关系。各 Mongrel 实例都运行一个单独的端口上。
要提供负载平衡,您必须为 Web 服务器安装扩展模块。举例来说,Apache HTTPD 需要 mod_proxy_balancer 和 mod_rewrite 模块。LightTPD 则需要 mod_proxy 模块。传统的部署架构如图 2 所示。
图 2. 传统 Ruby-on-Rails 部署
|
最后,部署需要一个管理工具(通常为 Capistrano)将应用程序部署到多个服务器中。如果您需要重新部署应用程序,则必须使用 Capistrano 重新启动所有的 Mongrel 实例。如果引入了另一个需要托管的应用程序,则必须复制整个配置。
创建 JRuby-on-Rails 应用程序
可以使用以下命令创建 JRuby-on-Rails 应用程序:
在本例中,hello 是应用程序的名称。
创建 Rails 应用程序的命令将根据 CoC 和 DRY 原则生成一个目录结构。图 3 显示了 JRuby 1.0.3 生成的目录结构,命令为 jruby -S rails hello。
图 3. Ruby-on-Rails 应用程序的目录结构
|
您可以使用 JRuby 调用所有的标准 Rails 命令,比如说启动服务器的 script/server 命令:
可以使用以下命令创建一个控制器和一个关联视图:
jruby script/generate controller home index
|
借助 JRuby 解释程序,您可以只使用纯 Ruby gem 和标准 Rails 命令轻易地测试任何 Ruby-on-Rails 应用程序。
Ruby-on-Rails 插件
Ruby-on-Rails 插件是专用于 Ruby on Rails 的功能完备的库。Ruby-on-Rails 插件扩展或修改了核心 Ruby-on-Rails 框架。它们便利了对其他代码的重用,或封装自己的代码以供重用。与 gem 不同,插件直接安装到具体的 Ruby-on-Rails 应用程序中。然后,插件将与应用程序一起远程部署。
Ruby-on-Rails 插件的一个例子是 Goldspike 项目,即原来的 Rails Integration,它使您能够通过 Ruby-on-Rails 创建 Web ARchive(WAR)。WAR 格式是在兼容 Java EE 的应用服务器中分发和部署应用程序的标准方式。
GlassFish 应用服务器是由 GlassFish 社区 开发的一款开源的、兼容 Java EE 5 的应用服务器。Sun 支持的 GlassFish 版本是 Sun Java System 应用服务器。
除了应用服务器之外,GlassFish 社区还开发了许多其他有用的组件,比如说:
GlassFish 社区还针对所有这些组件维护了一个 maintains a Maven 存储库。
GlassFish 应用服务器的当前发行版是 GlassFish v2,它拥有以下主要特性:
- Metro:一个完整的 Web 服务栈,提供了与 .NET 3.0 的互操作性。
- 集群、负载平衡和高可用性
- 通过 OpenESB 支持 Java Business Integration (JBI)
- 比 GlassFish v1 更佳的用户体验
- 单一下载,空间更小
- 多用户配置文件
- 更快的启动时间
- 更新中心
- 改进的管理控制台
- 记录集合性能:2007 年 7 月,GlassFish v2 使用一台 Sun Fire T2000 服务器 在 SPECjAppServer 上取得了最高的分数,领先当时的竞争者足足百分之 30。
您可以免费 下载 GlassFish 应用服务器。参见本文结束部分的 更多信息 一节,了解关于 GlassFish 应用服务器的更多信息。
GlassFish 社区正致力于下一版本的应用服务器:GlassFish v3。该版本的主要特性如下:
- 较小的内存占用:内核大小不超过 100 KB。
- 更快的启动时间:通常少于 1 秒。
- 模块化:只根据需要启动容器。
- 对脚本语言的扩展支持:除了 Java EE 和 JRuby 之外,开发工作还专注于对 Groovy/Grails、Phobos、PHP 和 Jython/Python 的支持。
此处 提供了技术预览版本的 GlassFish v3。稳定版本计划于 2008 末发布。
在 GlassFish 应用服务器上部署 JRuby-on-Rails 应用程序
您可以使用以下两种模式来部署 JRuby-on-Rails 应用程序:基于 WAR 或基于 Directory。
基于 WAR 模式
Web ARchive (WAR) 是在 Java EE 服务器上分发和部署应用程序的标准封装格式。要部署为基于 WAR 模式,您必须安装 Goldspike 插件,该插件使您能够通过 Ruby-on-Rails 应用程序创建 WAR。Goldspike 插件为 Ruby-on-Rails 应用程序提供了一个封装格式和调试机制。创建好 WAR 文件之后,您可以将它部署到 GlassFish。
图 4 展示了部署在 GlassFish 应用服务器上的 WAR 文件的流程图。
图 4.基于 WAR 部署流程图
|
对于连接管理,GlassFish 使用 Grizzly,它是使用 Java NIO API 编写的 HTTP 监听程序实现。GlassFish 应用服务器中的 Grizzly 监听程序将接收请求并将它分发给合适的 Web 应用程序。WAR 文件中的 web.xml 文件包含 servlet org.jruby.webapp.RailsServlet,用于将 servlet 请求中的数据转换为 Rails 调试程序。JRuby 运行时将产生多个 Rails 实例,可以通过 GlassFish 来配置它们。
Warbler(Ruby gem)提供了一种备选封装机制,该机制轻便、灵活且更类似于 Ruby。它使用 Goldspike 进行 servlet 调度。有关 Warbler 的详细信息,请访问 JRuby wiki。
基于 Directory 模式
在基于 Directory 部署模式中,我们将 Rails 应用程序直接部署到 GlassFish 中,而不需要任何额外的插件。
Grizzly 连接器接收请求并将它直接分发给一个预定义的 JRuby 安装。每次 Grizzly 监听程序接收到一个请求时,JRuby 运行时都会生成一个新的 Rails 实例。
图 5. 基于 Directory 部署流程图
|
在基于 WAR 和基于 Directory 模式中,只有一个 Java Virtual Machine* 将作为 GlassFish 应用服务器的操作系统进程运行。基于 Directory 模式的主要优势在于它绕过了 Web 应用程序处理并且将请求直接委托给 Rails 框架。
在 GlassFish v2 上部署 JRuby-on-Rails 应用程序
GlassFish v2 用户可以添加 JRuby 功能,方法是通过 GlassFish 更新中心 GUI 下载 JRuby 模块。GlassFish 更新中心是绑定在 GlassFish 应用服务器中的一款实用工具,您可以通过它更新已有功能或添加新功能。JRuby 模块可以通过 Ruby-on-Rails 应用程序创建孤立或共享的 WAR 文件。然后,WAR 可以部署到 GlassFish 应用服务器实例中。
图 6 显示了 GlassFish 更新中心 GUI 中可用的 JRuby on GlassFish 模块。您也可以查看 比较详细的屏幕,它提供了安装和使用 JRuby-on-GlassFish 模块的命令。
图 6. GlassFish 更新中心 GUI
单击图像查看大图。
|
孤立 WAR 文件 具有完备的功能,并且在应用程序中绑定了所有必需的库:比如说 JRuby、Rails 和 Goldspike 。共享 WAR 文件 只包含应用程序的部署描述符。对于共享 WAR,我们配置 GlassFish 应用服务器提供任何必需的库。
如果您选择构建一个孤立 WAR 文件,以避免配置 GlassFish 服务器,则需要为以部署后 WAR 文件的大小为代价。对于普通的 Hello World 应用程序,扩展后的孤立 WAR 文件大小为 10.6 MB,而共享 WAR 文件的大小为 202 KB。
在 GlassFish v3 Gem 上部署 JRuby-on-Rails 应用程序
如果您已经在系统上安装了 JRuby,则可以下载 GlassFish v3 gem 并使用以下命令将它安装到 JRuby 实例中:
jruby -S gem install glassfish
|
该命令将安装 gem 并从 WEBrick 或 Mongrel 顺利转换为使用 GlassFish 部署和开发应用程序。使用 gem,您将在基于 Directory 模式部署应用程序。
有关安装和使用 GlassFish gem 的完整命令,请参阅此 博客条目。
使用 GlassFish 应用服务器部署 JRuby-on-Rails 的优势
以下部分将从 Rails 和 GlassFish 的视角解释应用程序和部署的关键概念。
相同的开发和部署环境
通常,我们开发 Ruby-on-Rails 应用程序所使用的环境与其部署环境有着相当大的差异。开发环境使用 WEBrick 服务器测试应用程序,而部署环境则需要使用 Capistrano 管理复杂配置。
在使用 GlassFish 应用服务器时,JRuby-on-Rails 应用程序的部署环境与它的部署环境完全相同。在 GlassFish 环境中,一个进程将监听所有的请求并处理响应。相反,传统的 Ruby-on-Rails 开发则涉及多个进程。
在 GlassFish 环境中,从开发到生产的迁移不需要任何额外配置。您可以使用相同的容器用于开发和生产。GlassFish 允许多个应用程序托管在同一个域中。简而言之,GlassFish 提供了一个简化和集成的开发和部署容器,而不需要配置多个工具。
一个容器托管多个应用程序
如果您部署拥有各种不同功能的多个 Rails 应用程序,传统部署要求将各个应用程序部署到 Mongrels 的不同包中。从本质上说,您必须对各个应用程序重复整个设置,使用 Mongrels 作为由 Capistrano 管理的轻量级 Web 应用程序的后台。
借助 GlassFish 应用服务器,您可以在运行中的 GlassFish 实例中部署多个应用程序。我们将在一个单独的上下文中部署各个应用程序,并使用它们各自的资源集合,同时完全分离各个应用程序。我们通过复制更新文件重新部署应用程序,无论是基于 WAR 或基于 Directory 模式,而不需要重新启动 GlassFish。
通过一个应用程序发送多个请求
在 Rails 中,应用程序能够处理的请求数量直接与运行在包中的 Mongrels 的数量成比例关系。尽管可以轻易地扩展应用程序(只需添加更多的 Mongrels),但这在资源占用方面耗费巨大。
GlassFish 应用服务器可以处理多个请求。您可以在配置 GlassFish JRuby 运行时的时候指定请求的数量。GlassFish 在连接池中维护这些运行时。当 GlassFish 接收到请求时,它将使用池中的 JRuby 运行时生成新 Rails 实例来处理请求。返回响应之后,JRuby 运行时将返回连接池并可以供下一个请求使用。
如前所述,基于 WAR 部署模式将使用 Goldspike 插件。第一次运行 Goldspike 时,它将在 JRuby-on-Rails 应用程序目录下创建一个描述符文件 WEB-INF/web.xml。您可以在该文件编辑以下上下文参数,以配置 JRuby-on-Rails 实例的数量:
 |
|
jruby.pool.maxActive
|
最大运行时数量
|
4
|
|
jruby.pool.minIdle
|
最小运行时数量
|
2
|
|
jruby.pool.initialSize
|
运行时初始数量
|
jruby.pool.minIdle 的值
|
|
jruby.pool.checkInterval
|
检查是否需要更多运行时之间的毫秒数
|
1000
|
在基于 Directory 模式中,您使用命令行属性 -n 控制运行时的数量。举例来说,以下命令将启动两个 JRuby-on-Rails 实例:
jruby -S glassfish_rails temp -n 2
|
重新部署应用程序
在传统部署中重新部署 Ruby-on-Rails 应用程序时,您必须停止整个 Mongrels 包,将应用程序复制到部署目录,然后再启动 Mongrels。
在 GlassFish 应用服务器中重新部署应用程序时,需要将一个新的 WAR 文件复制到部署目录。GlassFish 将循环所有需要的资源,包括各种类和数据库连接。不需要重新启动已经运行的 GlassFish 实例,因此相同 GlassFish 实例中的其他应用程序可以继续处理请求,而不会中断。
集群、负载平衡和高可用性
传统 Rails 部署中的集群表示维护一个 Mongrel 集群:Mongrels 包作为轻量级反向代理服务的后台,如 Apache、LightTPD 或 nginx。您必须单独配置集群中的各台机器,然后使用轻量级 Web 服务器对它提供反向代理。
部署 Mongrels 包上的 Ruby-on-Rails 应用程序不共享任何状态,因为 Ruby on Rails 是单一线程的。多个应用程序之间惟一的公共链接是轻量级 HTTP 服务器(作为 Mongrel 包的前台),或位于后台的数据库。
相反,图 7 展示了 GlassFish 应用服务器是如何为集群、负载平衡和高可用性提供统一管理的。
图 7. GlassFish 集群架构
|
在 GlassFish 集群中,每个节点(一台物理机器)都运行在一个或多个应用服务器实例中。每个节点还附带一个节点代理,用于与中心管理服务器通信。图 7 展示了一些节点组成的集群实例。
图 7 展示了各种传输(HTTP、JMS、RMI-IIOP)通过负载平衡层与集群实例通信。企业信息系统等自定义资源将通过 Java 连接器架构中的资源适配器连接到负载平衡层。所有传输都可以在集群中实现负载平衡,通过在单点故障时使用冗余单元实现可伸缩性和容错性。
位于图片底部的是高可用性应用程序状态存储库,它是会话状态存储的抽象。存储库保存会话状态,包括 HTTP 会话状态、Ruby-on-Rails 会话状态和单点登录信息。这些状态信息可以通过内存复制保存或存储在数据库中。
集群和高可用性集成在 GlassFish v2 中。它通过插件提供负载平衡,因此我们可以轻易地配置所有集群实例。有关详细信息,请阅读 Clustering in GlassFish Version 2 一文。
数据库连接池
在传统部署中,Rails 应用程序每次请求访问数据库时,Mongrel 服务器都将创建一个新的数据库连接。但是为每个请求都创建一个新的连接将花费更多的时间和资源。
GlassFish 应用服务器提供数据库连接池,后者可最大程度地延缓与数据库相关的操作。所有部署的应用程序都可以使用数据库连接池。当客户机请求连接时,连接将通过池提供。当客户机不再需要连接时,连接将返回池。这种策略允许后继数据库请求在每次连接请求时重用新连接。因此,连接池改善了应用程序打开、使用和关闭连接的响应时间,因此池将管理与数据存储的实际连接。
有关使用基于 JNDI 数据库连接池的完整指令集,请阅读此 博客条目。
同时托管 Ruby-on-Rails 和 Java EE 应用程序
Java EE 平台是一个针对企业级部署的、行业级的、久经考验的平台。GlassFish 是一个 Java EE 5 兼容的应用服务器,它还可以托管 JRuby-on-Rails 应用程序。通过允许 Java EE 与 JRuby-on-Rails 代码混合,GlassFish 可以利用已有的 Java EE 投入,同时在相同的环境中托管 JRuby-on-Rails 应用程序。
本节将介绍 mediacast.sun.com,它是在 GlassFish 应用服务器上部署 JRuby-on-Rails 的成功示例。
可公开访问的 Sun 媒体网站 为 Sun 员工提供了一个存储大型媒体文件的场所。应用程序使用 JRuby on Rails 编写并且部署在 GlassFish 应用服务器上。图 8 所示的部署图描述了两个负载平衡的 Sun Fire T2000 服务器servers 运行在 Solaris 10 操作环境 和 GlassFish v2 上:实际上是 Sun Java System 应用服务器 9.1 UR1。
图 8. Sun 媒体部署图
|
NetBeans IDE 6 和 GlassFish v2 应用于应用程序的开发阶段。有关开发的详细信息,以及此示例的经验,请阅读 由 Igor Minar 撰写的博客条目。
使用 JRuby-on-Rails 和 GlassFish 开发和部署应用程序具有许多传统部署无法比拟的优势。其主要优势如下:
- 可以在同一个环境中进行开发和部署。GlassFish 使这两种活动都可以方便地使用相同的服务器。
- 可以在已经运行的 GlassFish 实例中部署多个应用程序。不需要为其他托管的应用程序中断服务。您还可以重新部署应用程序,而不需要重新启动 GlassFish。
- 通过在池中维护 JRuby 运行时,GlassFish 可以处理多个请求。响应请求后,JRuby 运行时将返回池并可供下一个请求使用。
- GlassFish 应用服务器提供了一些数据库连接池,后者可以最大程度地减少数据库相关操作的延时。
- 集群和高可用性集成于 GlassFish v2 中。负载平衡由一个可轻易管理的插件提供。
- GlassFish 可以利用已有的 Java EE 平台投入,并在相同环境中托管 JRuby-on-Rails 应用程序。
_______
*在本页面中,术语 "Java Virtual Machine" 或 "JVM" 表示 Java 平台上的一种虚拟机。