在 Mac OS X Snow Leopard 上安装 Ruby 和 Rails

昨天刚发布的 Rails 3.0.6 包含重要的安全更新,所以刚好在升级 Rails 的时候顺便把 Ruby 也升级一下。Mac OS X Snow Leopard 默认的 Ruby 版本是 1.8.7 的,貌似直接源代码编译升级到 1.9.2 有一些问题(网上有不少人升级到 1.9.2 的时候出问题)。最好的办法是用 RVM (Ruby Version Manager),又简单又方便,而且不会替代系统自带的 Ruby 1.8.7,以后可以随时在 1.8.7 和 1.9.2 之间切换,适合开发和移植程序,Rails 3 也支持 Ruby 1.9.2 版本。

安装必要工具

安装前确定 Mac OS X 已经安装了最新的 Xcode 开发工具,至少是 3.2.1 版本。然后安装 git 工具:

$ xcodebuild -version
Xcode 3.2.6
Component versions: DevToolsCore-1809.0; DevToolsSupport-1806.0
BuildVersion: 10M2518

$ sudo port install git

安装 RVM

安装 RVM 的方法有点不同:

$ bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )

如果有代理的话,用 -x 设置代理服务器:

$ bash < <( curl -x 192.168.0.1:3128 http://rvm.beginrescueend.com/releases/rvm-install-head )

配置 RVM:

$ vi ~/.bashrc
# This loads RVM into a shell session.
[[ -s "/Users/vpsee/.rvm/scripts/rvm" ]] && source "/Users/vpsee/.rvm/scripts/rvm"

关闭 Terminal 后重新打开以便 .bash_profile 文件生效,这个时候用下面命令可以验证 rvm 是否安装成功:

$ type rvm | head -n1
rvm is a function

安装 Ruby

安装最新的 Ruby 1.9.2-p180 稳定版本:

$ rvm install 1.9.2

系统上原来是 1.8.7 的,把系统默认的 ruby 解释器设置成 1.9.2:

$ ruby -v
ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]
$ rvm --default 1.9.2
$ ruby -v
ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-darwin10.7.0]

检查 gem 版本是 1.3.7 或以上,以及 sqlite3 版本是 3.6.12 或以上,然后使用 gem 安装 sqlite3-ruby:

$ gem -v
1.3.7

$ sqlite3 -version
3.7.5

$ gem install sqlite3-ruby
/Users/vpsee/.rvm/rubies/ruby-1.9.2-p180/bin/gem:4: warning: Insecure world writable dir /usr/local/bin in PATH, mode 040777

$ sudo chmod go-w /usr/local/bin
$ gem install sqlite3-ruby

安装 sqlite3-ruby 的时候出现目录权限警告, 修改一下 /usr/local/bin 的权限就好了。

安装 Rails

安装 Rails 3.0.6 版本:

$ gem install rails

$ rails -v
Rails 3.0.6

升级 Ruby 和 Rails 完毕后我们就在 Snow Leopard (Mac OS X 10.6.7) 上有了一个最新的 Ruby on Rails 开发环境。

CentOS 5 上部署 Nginx、Mongrel 和 Rails

接着昨天的来,昨天 VPSee 简单的安装和试用了一下 Redmine,发现 Redmine 的界面很简单清新、使用也很方便,需要的功能都有。今天打算部署到稍微专业一点的环境,Ruby on Rails 的部署方案主要有以下几种:

  • Lighttpd + FastCGI
  • Nginx + Mongrel
  • Nginx + Thin
  • Nginx + Phusion Passenger
  • Apache2 + Thin
  • Apache2 + Phusion Passenger (Mod_Rails)

目前用的比较多、比较成熟的要算 Nginx + Mongrel 和 Apache2 + Passenger 了,Apache2 + Passenger 配置很简单,非常适合多 ruby app 的部署。考虑到成熟、稳定、而且 VPSee 对 Nginx 比较熟悉,所以选定 Nginx + Mongrel 组合作为 Redmine 环境的部署方案。以下的内容虽然以 Redmine 为例来描述如何部署 Nginx + Mongrel,其配置方法也适用与一般 Rails 程序部署的情况。

安装和配置 Ruby on Rails

详细参考 “CentOS 5 上配置 Redmine 和 Git” 中的 “安装必要的软件包” 和 “安装和配置 Ruby on Rails”.

安装和配置 Mongrel

拷贝 mongrel_cluster 启动文件到 /etc/init.d/,在 /etc 下创建一个目录 mongrel_cluster 用来存放 mongrel 程序的配置文件,配置文件必须以 yml 扩展名结尾,不能是 yaml,最后修改 yml 配置文件,注意 user/group 要和前面一文的对上,否则 mongrel_cluster 启动不了:

# gem install mongrel
# gem install mongrel_cluster

# cp /usr/local/lib/ruby/gems/1.8/gems/mongrel_cluster-1.0.5/resources \
/mongrel_cluster /etc/init.d/
# chmod +x /etc/init.d/mongrel_cluster
# /sbin/chkconfig --level 345 mongrel_cluster on

# mkdir /etc/mongrel_cluster
cp /usr/local/lib/ruby/gems/1.8/gems/mongrel_cluster-1.0.5/resources/defaults.yaml /etc/mongrel_cluster/redmine.yml

# vi /etc/mongrel_cluster/redmine.yml
---
cwd: /home/redmine/
port: "9000"
environment: production
address: 127.0.0.1
pid_file: log/mongrel.pid
servers: 4
group: redmine
user: redmine

启动 mongrel:

# /etc/init.d/mongrel_cluster start

安装配置 Nginx

安装完 nginx 后需要修改配置文件,nginx 支持模块化配置,为了更清晰最好把全局配置文件和 virtal host 配置文件分开,先是修改 nginx 的全局配置文件:

# yum install nginx

# vi /etc/nginx/nginx.conf
user              nginx;
worker_processes  1;
error_log         /var/log/nginx/error.log;
pid               /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] $request'
                      '"$status" $body_bytes_sent "$http_referer"'
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     off;
    keepalive_timeout  65;

    gzip  on;
    gzip_http_version 1.0;
    gzip_comp_level 2;
    gzip_proxied any;
    gzip_types text/plain text/html text/css application/x-javascript 
text/xml application/xml application/xml+rss text/javascript;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/vhosts/*;
}

接着在 /etc/nginx/ 下面创建一个文件夹 vhosts 用来存放多个 virtual host 局部配置文件:

# mkdir /etc/nginx/vhosts
# vi /etc/nginx/vhosts/vpsee.com.conf

upstream mongrel_server {
        server 127.0.0.1:9000;
        server 127.0.0.1:9001;
        server 127.0.0.1:9002;
        server 127.0.0.1:9003;
}

server {
        listen  80;
        server_name  vpsee.com www.vpsee.com;

        client_max_body_size 10M;
        root   /home/redmine;

        access_log  /var/www/access_vpsee.com.log  main;

        location / {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect false;
            proxy_max_temp_file_size 0;

            if (-f $request_filename) {
                break;
            }
            if (-f $request_filename/index.html) {
                rewrite (.*) $1/index.html break;
            }
            if (-f $request_filename.html) {
                rewrite (.*) $1.html break;
            }
            if (!-f $request_filename) {
                proxy_pass http://mongrel_server;
                break;
            }
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
}

启动 nginx:

# /etc/init.d/nginx start

打开浏览器应该就可以访问了。

Ravelry 的 Rails 架构

看多了超大规模高性能、超大数据库架构,有必要回到现实看看中等规模网站是如何架构的,毕竟不是每个网站、web app 都有机会做成 Google/Yahoo/Facebook/Amazon 那样。Ravelry 是一家用 Ruby on Rails 搭建的社区网站,学习一下 Ravelry 的 Rails 架构经验。

数据

数据和资料来源(2009):Ravelry

43万注册用户
每个月约20万用户上线,每天约7万用户登录
每天约360万 PV(只包括注册用户,不包括其他途径访问),实际 PV 大概1000万每天
每天约900新用户注册
论坛每天发布约5万个新帖
网站有230万个项目、190万个帖子、130万条消息、800万张图片(大部分保存在 Flickr)
包括创始人在内公司一共才3.5个人(其中一个是 part time)

技术架构

Ravelry 使用了以下一些 Open Source 项目和技术:

Gentoo Linux
MySQL
Ruby Enterprise Edition
Memcached
Nginx/HAProxy/Apache + mod_passenger
Tokyo Cabinet/Tyrant
Sphinx
Xen
Munin/Nagios/Syslog-ng
Amazon S3/Cloudfront

Ravelry 刚开始运行在一个 VPS 上,随着网站规模的变大逐渐转向自己的硬件,服务器是从 Silicon Mechanics 购买的,托管在 Hosted Solutions 和 Cogent。Ravelry 使用 Amazon S3 做存储,Amazon CloudFront 做 CDN。

Ravelry 目前总共有7台物理服务器,Xen 虚拟化后成13台,使用 Gentoo Linux 操作系统。其中:

  • 1台用来备份,1台用来测试;
  • 1台用来做 master 数据库服务器,1台做 slave 数据库服务器 + Sphinx 搜索引擎;
  • 另外3台用来做应用服务器,运行 Passenger,Ruby Enterprise Edition 和 Memcached。使用 Passenger 和 Ruby GC patches 节省了大量内存。

前端服务的架构大概像这样:nginx -> haproxy -> apache + mod_passenger,Ravelry 的创始人 Casey 提到他们主要的 scaling/tuning/performance 方面的工作还是集中在数据库部分。

Ravelry 使用 Capistrano 来快速部署新版本的网站程序,使用 Munin 来监测服务器资源、Nagios 来警告、Syslog-ng 来做日志,使用 Memcached 来缓存数据库对象,部分需要缓存 larger object 的地方用到了 Tokyo Cabinet/Tyrant。Ravelry 几乎把站内所有的用到 Markdown 标记语法的页面都缓存成了普通的 HTML。

Ravelry 在开始上线的头几个月几乎每天都会修正 bug、推出新版本,得益于 Ruby 的快速开和 prototype 的能力。Casey 说,Ruby is fun! Fun is important.