前言:为什么要研究Ruby on Rails的部署
学习Ruby on Rails已经一段时间了,一直使用自带的WEBrick服务器进行开发。
WEBrick是一款纯Ruby编写的服务器,使用方便,很适合开发环境下进行系统调试。但是它不支持多线程访问,换句话说,所有的Ruby请求都是按照到达的时间先后,顺序处理的,因此效率不高,无法应用在实际的生产环境中。所以今天研究了一下如何将Rails3应用部署到真实的线上环境中。
搜集了一下当前比较流行的Rails部署方案,这些资料里面介绍了许多可选的方案:
1、Agile Web Development with Rails (4th edition),Chapter 16;
2、范凯的博客:在Linux平台上安装和配置Ruby on Rails详解;
3、一个日本开发者的博客:Rails 3.0.0rc + lighttpd + FastCGI で無理矢理動かしてみた。
其中,范凯在RoR部署方案深度剖析一文中详细列举和分析了各种方案的优缺点以及性能上的差异,十分有借鉴意义。他认为各个方案在性能方面的排序为:
Lighttpd+FastCGI > Lighttpd+Mongrel > Nginx+Mongrel > Apache+Mongrel > Ngignx+FastCGI > Apache+FastCGI
因此,本文也采取了和他相同的部署方案。但是,由于他的博客较老,Ruby on Rails两年来从2.x升级到了3.x,以前的部署步骤也发生了变化,按照他的方法已经无法成功部署Rails3应用了。因此,本文根据相关资料,进行了些尝试。
我使用的环境如下:
1、Linux ubuntu 2.6.32-32-generic #62-Ubuntu SMP Wed Apr 20 21:54:21 UTC 2011 i686 GNU/Linux
2、gcc version 4.3.4 (Ubuntu 4.3.4-10ubuntu1)
在开始部署之前,请确保你有一个Unix系统和较高版本的gcc编译器。
一、安装Ruby解释器
现在Ruby提供了针对Ubuntu平台的deb安装包,并且你也可以使用apt-get安装Ruby解释器,但是我仍然建议自行下载Ruby源代码编译安装。因为可以自己定制Ruby安装的路径,并且可以在编译过程中自行添加更多的特性,还可以自己控制安装的版本。
Ruby的源代码可以从Ruby官方网站下载:Ruby解释器下载
下载源代码包到本地Linux主机,然后解压缩,进入该目录,进行配置,编译和安装:
tar xvfz ruby-1.9.2-p180.tar.gz
cd ruby-1.9.2-p180
./configure -prefix=/opt/ruby-1.9.2-p180
make && make install
如果想浏览所有的configure参数,可以:
./configure -h
如果不定制安装的目录,默认将安装到/usr/local目录下面。然而我建议自行定制一个ruby的安装目录,例如/opt/ruby-1.9.2-p180,这样便于以后的升级,不会和操作系统其他软件混在一起。而且今后可能会安装其他版本的Ruby解释器,通过分开目录安装还可以在不同的Ruby解释器之间切换。
安装好以后,我比较喜欢在/usr/local/bin下面建立软连接的方式来把Ruby加入系统搜索路径:
ln -s /opt/ruby-1.9.2-p180/bin/ruby /usr/local/bin/ruby
ln -s /opt/ruby-1.9.2-p180/bin/gem /usr/local/bin/gem
二、安装Ruby on Rails
确认服务器已经连接互联网的情况下执行:
gem install rails
即通过gem从rubyforge网站下载rails所有依赖包安装。
安装好rails以后,可以执行:
ln -s /opt/ruby-1.9.2-p180/bin/rails /usr/local/bin/rails
rails –v
确认一下rails的版本。
三、安装Ruby的数据库适配器
Rails发行包中已经自带纯Ruby的MySQL数据库适配器,然而对于生产环境来说,我们仍然应该下载安装C版本的数据库适配器,以达到更好的性能。Rails升级到3.0之后,推荐使用mysql2作为MySQL驱动,从这里可以下载mysql2-0.2.11.gem
gem install mysql2-0.2.11.gem -l -- --with-mysql-dir=/opt/mysql5
注意--with-mysql-dir应该指向MySQL数据库的安装路径,如果数据库服务器和Web服务器不在同一台机器上,那么Web服务器上也必须安装MySQL软件,因为ruby的C版本MySQL适配器需要在编译的时候联接MySQL的系统库。
四、安装fcgi支持库
由于Ruby的fcgi支持库需要在编译的时候联接fcgi的系统库,因此我们需要先安装fcgi库,下载fcgi源代码发行包fcgi-2.4.0.tar.gz
tar xzvf fcgi-2.4.0.tar.gz
cd fcgi-2.4.0
./configure --prefix=/opt/fcgi-2.4.0
make && make install
同样,将fcgi安装在自己指定的目录下,而不是默认的/usr/local,避免多个软件混在一起。
五、安装Ruby的FCGI支持
接下来就可以安装ruby的fcgi支持库了,下载fcgi-0.8.8.tgz
tar xzvf fcgi-0.8.8.tgz
cd fcgi-0.8.8
ruby install.rb config -- --with-fcgi-include=/opt/fcgi-2.4.0/include --with-fcgi-lib=/opt/fcgi-2.4.0/lib
ruby install.rb setup
ruby install.rb install
注意:安装完毕之后,请确保/opt/ruby-1.9.2/lib/ruby/site_ruby/1.9.1/i686-linux/目录下有这三个共享库文件:fcgi.so mysql.so openssl.so,否则运行中会出现问题。如果缺少fcgi.so请重复步骤五,如果缺少mysql.so请重复步骤三,如果缺少openssl.so,请安装openssl库之后重复步骤一。
六、安装Lighttpd Web Server
在安装lighttpd之前,应该确认操作系统已经安装pcre,即Perl兼容的规则表达式库。
如果没有,请执行:
sudo apt-get install libpcre3 libpcre3-dev
然后下载Lighttpd:
http://www.lighttpd.net/download/
tar xzvf lighttpd-1.4.28.tar.gz
cd lighttpd-1.4.28
./configure --prefix=/opt/lighttpd-1.4.28
configure完毕以后,会给出一个激活的模块和没有激活模块的清单,可以检查一下,是否自己需要的模块都已经激活,在enable的模块中一定要有“mod_rewrite”这一项,否则重新检查pcre是否安装。然后编译安装:
make && make install
七、配置Lighttpd
将Lighttpd的示例配置文件拷贝到配置文件目录中放置:
mkdir /etc/lighttpd
cp ./lighttpd-1.4.28/doc/config/lighttpd.conf /etc/lighttpd/
cp ./lighttpd-1.4.28/doc/config/modules.conf /etc/lighttpd/
同时可以根据你的实际情况进行修改,主要修改如下:
1)对/etc/lighttpd/modules.conf进行如下修改:
server.modules = (
"mod_access",
"mod_alias",
"mod_auth",
"mod_evasive",
"mod_redirect",
"mod_rewrite",
"mod_setenv",
"mod_usertrack",
"mod_fastcgi",
"mod_simple_vhost",
"mod_compress",
"mod_accesslog",
)
这个文件设置了lighttpd需要开启的模块。
2)对/etc/lighttpd/modules.conf进行如下修改:
server.document-root, server.error-log,accesslog.filename需要指定相应的目录,如果没有创建对应的目录,lighttpd启动时会报错。
3)用什么权限来运行Lighttpd
server.username = "USER_NAME"
server.groupname = "USER_GROUP"
从安全角度来说,不建议用root权限运行Web Server,可以自行指定普通用户权限。
4) 配置Lighttpd和Ruby on Rails之间的通信
这一步配置十分重要,最简单的配置如下:
$HTTP["host"] =~ "(^|\.)testmengli\.com" {
server.document-root = "/home/jowett/mini/public"
server.error-handler-404 = "/dispatch.fcgi"
fastcgi.server = (".fcgi" =>
("localhost" =>
(
"min-procs" => 1,
"max-procs" => 2,
"socket" => "/home/jowett/mini/tmp/socket/rails.socket",
"bin-path" => "/home/jowett/mini/public/dispatch.fcgi",
"bin-environment" => ("RAILS_ENV" => "development")
)
)
)
}
即由lighttpd启动2个FCGI进程,lighttpd和fcgi之间使用本机Unix Socket通信。
socket:指定了通信的socket文件的存放位置;
bin-path:指定了request转发的程序位置;
server.error-handler-404:指定了请求的资源找不到时,进行处理的程序。相当于把动态请求过滤给Ruby on Rails服务器进行处理。
5) 配置mime
必须设置mime配置文件,不然lighttpd无法识别css、image等资源类型。
在/etc/lighttpd/lighttpd.conf中添加一行:
include "mime.conf"
然后创建mime配置文件:
touch /etc/lighttpd/mime.conf
并且加入如下内容:
## MimeType handling
## -------------------
##
## Use the "Content-Type" extended attribute to obtain mime type if
## possible
##
mimetype.use-xattr = "disable"
##
## mimetype mapping
##
mimetype.assign = (
".pdf" => "application/pdf",
".sig" => "application/pgp-signature",
".spl" => "application/futuresplash",
".class" => "application/octet-stream",
".ps" => "application/postscript",
".torrent" => "application/x-bittorrent",
".dvi" => "application/x-dvi",
".gz" => "application/x-gzip",
".pac" => "application/x-ns-proxy-autoconfig",
".swf" => "application/x-shockwave-flash",
".tar.gz" => "application/x-tgz",
".tgz" => "application/x-tgz",
".tar" => "application/x-tar",
".zip" => "application/zip",
".mp3" => "audio/mpeg",
".m3u" => "audio/x-mpegurl",
".wma" => "audio/x-ms-wma",
".wax" => "audio/x-ms-wax",
".ogg" => "application/ogg",
".wav" => "audio/x-wav",
".gif" => "image/gif",
".jpg" => "image/jpeg",
".jpeg" => "image/jpeg",
".png" => "image/png",
".xbm" => "image/x-xbitmap",
".xpm" => "image/x-xpixmap",
".xwd" => "image/x-xwindowdump",
".css" => "text/css",
".html" => "text/html",
".htm" => "text/html",
".js" => "text/javascript",
".asc" => "text/plain",
".c" => "text/plain",
".cpp" => "text/plain",
".log" => "text/plain",
".conf" => "text/plain",
".text" => "text/plain",
".txt" => "text/plain",
".spec" => "text/plain",
".dtd" => "text/xml",
".xml" => "text/xml",
".mpeg" => "video/mpeg",
".mpg" => "video/mpeg",
".mov" => "video/quicktime",
".qt" => "video/quicktime",
".avi" => "video/x-msvideo",
".asf" => "video/x-ms-asf",
".asx" => "video/x-ms-asf",
".wmv" => "video/x-ms-wmv",
".bz2" => "application/x-bzip",
".tbz" => "application/x-bzip-compressed-tar",
".tar.bz2" => "application/x-bzip-compressed-tar",
".odt" => "application/vnd.oasis.opendocument.text",
".ods" => "application/vnd.oasis.opendocument.spreadsheet",
".odp" => "application/vnd.oasis.opendocument.presentation",
".odg" => "application/vnd.oasis.opendocument.graphics",
".odc" => "application/vnd.oasis.opendocument.chart",
".odf" => "application/vnd.oasis.opendocument.formula",
".odi" => "application/vnd.oasis.opendocument.image",
".odm" => "application/vnd.oasis.opendocument.text-master",
".ott" => "application/vnd.oasis.opendocument.text-template",
".ots" => "application/vnd.oasis.opendocument.spreadsheet-template",
".otp" => "application/vnd.oasis.opendocument.presentation-template",
".otg" => "application/vnd.oasis.opendocument.graphics-template",
".otc" => "application/vnd.oasis.opendocument.chart-template",
".otf" => "application/vnd.oasis.opendocument.formula-template",
".oti" => "application/vnd.oasis.opendocument.image-template",
".oth" => "application/vnd.oasis.opendocument.text-web",
# make the default mime type application/octet-stream.
"" => "application/octet-stream",
)
八、启动Lighttpd
在/etc/hosts文件中加入下面一行:
127.0.0.1 testmengli.com
Lighttpd的启动命令是:/usr/local/lighttpd/sbin/lighttpd -f /etc/lighttpd/lighttpd.conf
通过以上步骤,就基本实现了Rails应用在生产环境下的部署,用到的技术包括Lighttpd+fcgi+mysql,希望对大家有帮助!