提升Ruby on Rails性能的几个解决方案

时间:2021-05-22

简介

Ruby On Rails 框架自它提出之日起就受到广泛关注,在“不要重复自己”,“约定优于配置”等思想的指导下,Rails 带给 Web 开发者的是极高的开发效率。 ActiveRecord 的灵活让你再也不用配置繁琐的 Hibernate 即可实现非常易用的持久化,Github 和 Rubygems 上丰富多样的 Rails 插件是 Rails 开发高效率的又一有力保障。Rails 是一个真正彻底的 MVC(Model-View-Controller) 框架,Rails 清楚地将你的模型的代码与你的控制器的应用逻辑从 View 代码中分离出来。Rails 开发人员很少或者可能从未遇到过某些代码该放于哪一层的困扰,在 Rails 的世界中,你的代码的职责很清楚的被定位,你可以轻松的决定出它们应该位于哪一层。Rails1.2 之后的版本开始支持 Rest Service,通过这些内嵌的特别,你在开发你 Web 应用,展现给用户 HTML 的页面的同时,几乎不费吹灰之力,就可又提供基于 Rest API 的 Web Service,另外,你也可以方便的像使用基本数据的 Model 一样的去消费第三方提供的基于 Rest API 的 Web Service。

通过搜索引擎,你可以找到很多类似于用 Ruby On Rails 十五分钟创建 Blog 系统等类似的使用 Rails 进行快速开发的文章。 Ruby On Rails 对于敏捷开发过程的也是非常友好,在 Rails 框架中集成了 Unit Test, Function Test 对你的 Model 和应用逻辑进行测试。通过这些,你不需要再安装任何插件或者程序库便可方便的进行测试驱动开发,通过 Watir 的支持,你可以轻松的用 Ruby 代码实现基于浏览器的自动测试。 另外,在 Rspec 等插件的支持下,你甚至可以进行行为驱动开发(Behaviour Driven Development),让你的测试代码变得更加有意义,也更加容易被客户所接受。

虽然 Rails 的优点你可以一下子列出很多,你也可能会拿出用 Java/Hibernate/Spring/Struts 和 Ruby On Rails 开发同样功能 Web 应用程序的代码行比较来举例,或者提供进行 Java/Hibernate/Spring/Struts 和 Ruby On Rails 开发所需要接受的培训资料的书籍的对比照片来举例,但我们都不可避免的会面对可伸缩性(Scalability)的问题。很多 Web 应用会面对大量的用户群,这样的应用会遇到很大的并发带来的性能的考验。 Rails 在这一点上,并没有让所有人信服,依然有很多的系统架构师和工程师对 Rails 是否适用于开发高负载高并发的 Web 应用持怀疑的态度。但不可否认,随着 twitter, friends for sale,basecamp 这类大负载量的应用的出现,Rails 也越来越被认识是可扩展的,这些成熟的应用也告诉我们,开发出同时处理数百万用户请求的 Rails 应用是可能的。Ruby On Rails 框架在可伸缩性上为人诟病无非集中于以下几点,Ruby 语言本身性能问题,Ruby On Rails 缺少成熟的高性能的应用服务器,对数据库扩展的支持,互联网上缺乏可熟可靠的网络提供商等等。 本文将从这些点出发,介绍具可伸缩性的 Rails 应用程序的部署架构,以及开发高性能的 Rails 应用程序的一些比较好的具体实践。

通常的 Web2.0 应用,特别是高负载的应用,除了 Web 和应用服务器选择 , 负载均衡这类部署需要面对的问题之外,通常还必须得面对后台任务,高性能全文搜索这些开发上的问题,这些在 Java 或者 PHP 这些比较成熟的开发环境里面都有比较成熟的方案,开发和架构人员通常都会有多种选择,结合具体应用做出架构设计。在新兴的 Rails 社区,这些还并不完善和成熟,本文将介绍一些高性能可伸缩的 Rails 应用程序的开发和部署的具体实践,针对通常 Web 2.0 网站所遇到的具体问题做出分析和解决方案,旨在给 Rails 开发者提供具体的参考。本文将介绍的内容可以用下图来综合表示:
图 1. 本文总体结构

使用 Nginx+Passenger 来替代 Apache+Mongrel 来部署 Rails 应用

事实上,进行 Rails 部署可以描述得非常简单,我们需要一些机器配置我们的环境,为了性能和成本,我们理所当然选用 Linux 系列的服务器,可选的有 CentOS,Debian, Ubuntu Server 等。本文的所有程序,命令以及代码如非特别说明,都默认是以 Linux 为基本环境的。 然后我们需要数据库存储我们的数据,我们可以选用免费的 Mysql,然后我们便开始开发我们的 Web 应用的 Rails 代码,部署时,我们需要支持 Ruby On Rails 的应用服务器让我们的 Rails 代码跑起来,这可能是 Rails 自带的 Webrick,当然这个可能性极小,也可能是 FastCGI, 或者是 Mongrel,Thin, Passenger 等等,然后我们通过 Apache,Nginx,Lighttpd,HAProxy 之类的 Web 服务器访问我们的应用服务器,这个访问可以直接通过 HTTP 协议,也可以是 FastCGI,或者是自定义的其它协议,如此这般,我们便可以通过浏览器访问我们的应用程序了。如下图所示,这便是通常的 Rails 应用程序部署结构。
图 2. Rails 应用程序部署结构

对于前端的 Web Server,Apache 是事实上的工业标准,在 Web 服务器市场,是占有率最高的,全球大量的网站采用 Apache 来部署他们的应用,Apache 是一款成熟稳定的 Web 服务器,功能非常强大,提供对几乎所有 Web 开发语言和框架的扩展支持,在对 Rails 框架的支持上,我们可以采用 mod_fcgid 模块,通过 FastCGI 协议与 Rails 进程通讯。或者利用 mod_proxy_balancer 对后端的独立的 Rails 服务器如 Thin Cluster,Mongrel Cluster 或者 Apach/Nginx+Passenger 进行 HTTP 分发。但 Apache 作为一个通用的服务器,在性能上和一些轻量型的 Web 服务器相差甚远。Apache 的 mod_proxy_balancer 模块的分发性能不高,比 Nginx 或者 HAproxy 都相差很多,另外,Apache 目前并不支持 Event(事件)模型,它仅支持 Prefork(进程)模式和 Worker(线程)模式,每处理一个链接,就需要创建一个进程或线程,而一些轻量级 Web 服务器如 Nginx 和 Lighttpd,则都很好地利用内核的事件机制提高性能,极大减少线程或进程数量,降低系统负载。

Nginx 是一个轻量级的高效快速的 Web 服务器,它作为 HTTP 服务器和反向代理服务器时都具有很高的性能。Nginx 可以在大多数 Unix like OS 上编译运行,并有 Windows 移植版。 Nginx 选择了 Epoll 和 Kqueue 作为开发模型,它能够支持高达 50,000 个并发连接数的响应,可以在内部直接支持 Rails 和 PHP 程序对外进行服务。另外,Nginx 作为负载均衡服务器,也可以支持作为 HTTP 代理服务器对外进行服务 , Nginx 不论是系统资源开销还是 CPU 使用效率都比 Apache 要好很多。当你打开 Nginx 官方网站,你会发现一个如此知名的 Web 服务器产品的官方主页竟然如此简单,其实,Nginx 本身就是一个安装非常简单,配置文件非常简洁,甚至可以在配置文件中使用 Perl 语法。

在处理静态文件上, Apache 和 Nginx 都可以胜任。但对于应用服务器或者是前端的负载均衡服务器,我们推荐 Nginx 而不是相对 Nginx 较为重量级的 Apache。

对于应用服务器,Mongrel 一度是最流行的部署方式,它的 HTTP 协议的解析部分是用 C 语言编写的,效率上有所保证。Mongrel 使用了 Ruby 的用户线程机制来实现多线程并发 , 但是 Ruby 并不是本地线程 ,Rails 也不是线程安全的,因此 Mongrel 在执行 Rails 代码的过程中,完全是加锁的状态,那和单进程其实也没有太大差别。所有我们在使用 Mongrel 来部署 Rails 应用程序时,一般是在后台启动一个 mongrel_cluster 来启动多个 Mongrel 进程,如我们在 mongrel_cluster.yml 中进行如下配置可以在 8000~8009 端口启动 10 个 Mongrel 进程。
清单 1. Mongrel_cluster.yml 配置

--- cwd: /var// gem install leehambley-railsless-deploy

结束语

本文着重使用 Ruby On Rails 来开发和部署 Web 应用时一些有用的具体实践,没有具体去介绍一些通常应用程序都需要面对的普遍问题,如数据库的优化和分布式部署,这是一个大并发的 Web 应用都需要面对和解决的问题,比如可以采用 master-slave 的方式去部署分布式的数据库,或者采用分库或者分表的方式对数据库进行拆分。另外,在运行 Rails 服务器或者其它后台应用程序时,通过还需要另外的进程去进行监控,如用 God 去监控 Rails 进程也是一个 Rails 应用通常都会采用的策略。另外,很多时候,可以采用更敏捷更轻量级的 Rack 去代替 Rails 来进行更高效的开发的提供服务。并且,Engineyard ,Joyent 以及 Heroku 等这类 Rails 网络提供商的涌现也在相当程度上坚定了用 Rails 开发和部署大规模大并发 Web 应用的信心。虽然 Ruby On Rails 自身的缺陷不可避免, 但是开发可伸缩的高性能的应用程序并不是不可能的。本文希望能够帮助 Rails 开发人员快速掌握一些具体实践,能够编写出并部署性能高伸缩性强的 Web 应用程序。

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章