以前部署 Rails 應(yīng)用使用的是 Nginx + Passenger,非常方便。這次沒用這個(gè)方案是因?yàn)槲屹I了一個(gè)每月2.5刀的最低配的 VPS,根本安裝不了 Passenger......。于是我在網(wǎng)上搜了一下其他方案,Rails 應(yīng)用服務(wù)器大概常見的有這么3種:unicorn、puma、passenger。3 個(gè)都支持集群, puma 和 passenger 企業(yè)版支持多線程,unicorn 不支持多線程。passenger 除了支持 ruby on rails 外也支持其他的語言,如 python、nodejs??雌饋韨€(gè)人使用 puma 是一個(gè)非常不錯(cuò)的選擇,免費(fèi)開源,功能強(qiáng)大,可配置性也很好,而且它是 rails 默認(rèn)的服務(wù)器。
大概的原理
Nginx 作為反向代理服務(wù)器,負(fù)責(zé)監(jiān)聽主機(jī)域名的 HTTP 請求。接到客戶端的請求后,通過 upstream 指令將請求交給 Puma 應(yīng)用服務(wù)器處理,它們之間通過 unix socket 建立連系。Puma 負(fù)責(zé)監(jiān)聽 sockets,接到請求后調(diào)用 APP 生成頁面,將結(jié)果返回給 Nginx 服務(wù)器,Nginx 再把結(jié)果返回給客戶。
Nginx + Puma 配置
1. 安裝 Nginx
unbuntu 下直接通過 apt-get 安裝就可以了。
sudo apt-get install nginx
nginx 配置文件 /etc/nginx/sites-enabled/default
upstream app {
// 改成實(shí)際 puma.sock 的文件路徑
server unix:/home/vagrant/foo/shared/sockets/puma.sock;
}
server {
listen 80;
// 改成實(shí)際服務(wù)器域名
server_name 192.168.1.2;
// 改成實(shí)際 APP 路徑
root /home/vagrant/foo/public;
try_files $uri/index.html $uri @app;
location @app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app;
}
error_page 500 502 503 504 /500.html;
keepalive_timeout 10;
}
安裝 Puma
在 Gemfile 文件里添加,rails 5 是默認(rèn)的,就不需要了。
gem 'puma', '~> 3.7'
執(zhí)行 bundle install。
puma 配置文件 config/puma.rb。
# workers 數(shù)改成實(shí)際 CPU 數(shù),可通過 grep -c processor /proc/cpuinfo 查詢
workers 1
threads 1, 6
daemonize true
rails_env = ENV['RAILS_ENV'] || "production"
environment rails_env
app_dir = File.expand_path("../..", __FILE__)
shared_dir = "#{app_dir}/shared"
bind "unix://#{shared_dir}/sockets/puma.sock"
stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true
pidfile "#{shared_dir}/pids/puma.pid"
state_path "#{shared_dir}/pids/puma.state"
on_worker_boot do
require "active_record"
ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])
end
新建 puma 的日志、PID、和 Sockets 文件夾。
mkdir -p shared/log shared/pids shared/sockets
設(shè)置 rails 生成環(huán)境的 SECRET_KEY。
生成 key
$ rake secret
打開 bash 配置文件
$ vim ~/.bashrc
添加環(huán)境變量
export SECRET_KEY_BASE="這里是 rake secret 生成的字符串"
重新加載 bash 配置
$ source ~/.bashrc
如果只是臨時(shí)試試,也可以在命令行上執(zhí)行
$ export SECRET_KEY_BASE="`rake secret`"
新建 puma 控制腳本
在 APP 目錄下新建 pumactrl.sh 文件
$ vim pumactrl.sh
#!/bin/bash
case "$1" in
"")
echo -n "please provide a parameter (start, stop, reload)."
;;
start)
echo -n "starting puma..."
puma
;;
stop)
echo "stoping puma..."
kill `cat "shared/pids/puma.pid"`
;;
reload)
echo "reloading puma..."
kill `cat "shared/pids/puma.pid"`
puma
;;
esac
重啟服務(wù)器
重啟 Nginx
$ sudo service nginx restart
啟動(dòng) puma 服務(wù)器
$ ./pumactrl.sh start
如果一切正常,打開瀏覽器就可以看到你的網(wǎng)站首頁了。不過我是反復(fù)試了很多次才成功的......。有時(shí)候編程的復(fù)雜性不在于代碼邏輯本身,而是其他很多繁雜瑣碎的東西同時(shí)揉在一起產(chǎn)生的。
有幾個(gè)點(diǎn)需要注意:
- 仔細(xì)檢查配置里的各種路徑
- puma 配置里的
bind "unix://#{shared_dir}/sockets/puma.sock"前綴是雙斜杠 - 如果是生產(chǎn)環(huán)境下,需要先執(zhí)行一下
rails assets:precompile - 出現(xiàn)問題的時(shí)候檢查日志
// nginx 日志 /var/log/nginx/error.log // puma日志 shared/log/puma.stderr.log // rails app 日志 log/production.log
小結(jié)
服務(wù)器雖然能正常跑起來了,但是沒有做更細(xì)致的配置,可能性能不是很好,這個(gè)得更深一步的研究才能做了。為了方便部署,可以將 capistrano3-puma Gem 添加進(jìn)來,這個(gè)留待下次完成。