
部署之使用 mina 来部署 Ruby on Rails 应用之 unicorn (八)
1. 介绍
unicorn是一个运行ruby应用的HTTP服务器。当你写完了ruby应用,准备部署时,就可以用它来运行ruby应用。但一般来说,我们不会直接那样用,我们会结合nginx来用,把高性能的nginx暴露在最外层,而反向代理到unicorn。nginx是一个静态web服务器,它是部署在80端口,一般来说,它会处理所有的静态文件请求,比如css,js等,假如需要动态的内容,它就会转发给unicorn,而unicorn做一些处理,比如查数据库等,处理完,再转交给nginx,最后nginx发送给用户,所以整个过程都是nginx在起一个缓冲和保护的作用,用户并没有感觉到unicorn的存在。
这种处理方式跟apache有很大的不同,比如说处理php的mod_php模块。apache也是跟nginx一样,是个静态服务器。它本身不能解析php解析,要解析php脚本,就必须得装php解析的组件,可以把这组件编译进apache中,也可以以动态加载的形式来加载。但无论怎样,这个模块本身就会在处理php请求时成为apache的一部分,处理的效率和性能就取决于这个模块本身。而nginx不一样,它处理ruby动态的请求和静态文件的请求是分开的,静态文件它自己能处理,而动态的,它通过反向代理来转发,这两部分本身就分开了,这样就很灵活了,因为nginx本身性能高,能起到保护的作用,而后面的unicorn进程也有自己的空间,可以尽量发挥自己的功能和作用。比如,unicorn也有类似于nginx的master-worker的进程模式,这样可以部署多个unicorn形成负载均衡。unicorn本身也是一个gem,这样就不用像mod_php那样编译或安装nginx的组件,这样很灵活,假如以后要把unicorn换成puma,也是很方便的事。
unicorn还支持copy-on-write-friendly(写时复制),高效利用内存。还支持监听到unix socket等功能。
unicorn是多进程的处理请求的模式,而且它还是预先folk(prefork)。也就是说,在启动服务的时候就会先创建好进程。一般来说,假如你有两个核心的cput,那就会创建一个master进程,两个worker进程,请求进来了,由master来分配给worker处理,这点跟nginx的机制差不多。
2. 使用
我们需要先把unicorn进程给跑起来,而它是以监听unix socket的方式跑的,而nginx也是把请求转发到unicorn的unix socket,unix socket是一种套接字,先把它想象成一个文件。
用mina来部署unicorn进程需要一个gem,叫mina-unicorn。
2.1 mina-unicorn
unicorn本身也是一个linux的命令行程序,而mina-unicorn就是根据unicorn命令结合linux的kill命令来封装的。它的源码也是比较简单的。
在Gemfile文件中添加下面一行。
gem 'mina-unicorn', :require => false
gem 'unicorn'
执行bundle安装。
添加下面一行到config/deploy.rb
文件中。
require 'mina/unicorn'
设置socket和pid文件放置的目录位置。
socket是unicorn监听的文件套接字,而pid是一个进程标识符,是个整数,linux一般用它配合kill指令来控制进程的启动,重启等,比如"kill cat /tmp/unicorn.pid
"。
# socket文件和pid文件会放在下面的目录中,这个可以查看源码获知详情。
set :shared_paths, ['tmp/sockets', 'tmp/pids']
找到config/deploy.rb
中task :setup => :environment
的部分,添加下面两段。
task :setup => :environment do
...
queue! %[mkdir -p "#{deploy_to}/#{shared_path}/tmp/sockets"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/#{shared_path}/tmp/sockets"]
queue! %[mkdir -p "#{deploy_to}/#{shared_path}/tmp/pids"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/#{shared_path}/tmp/pids"]
...
end
然后运行下面的命令。
mina setup
这个作用是在部署目录下的shared目录下生成tmp/sockets
和tmp/pids
目录。
做完这些,还差一步,就是需要部署完应用的时候,重启unicorn。
在config/deploy.rb
文件中找到task :deploy => :environment
部分添加invoke :'unicorn:restart'
这一行,如下所示。
desc "Deploys the current version to the server."
task :deploy => :environment do
to :before_hook do
end
deploy do
...
to :launch do
invoke :'unicorn:restart'
...
end
end
end
在config目录下新增一个文件叫unicorn.rb
,这个是unicorn的配置文件,内容如下:
app_path = File.expand_path( File.join(File.dirname(__FILE__), '..', '..'))
worker_processes 1
timeout 180
listen "#{app_path}/shared/tmp/sockets/unicorn.sock"
pid "#{app_path}/shared/tmp/pids/unicorn.pid"
stderr_path "log/unicorn.log"
stdout_path "log/unicorn.log"
before_fork do |server, worker|
if defined?(ActiveRecord::Base)
ActiveRecord::Base.connection.disconnect!
end
old_pid = "#{server.config[:pid]}.oldbin"
if File.exists?(old_pid) && server.pid != old_pid
begin
Process.kill("QUIT", File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH
# someone else did our job for us
end
end
end
after_fork do |server, worker|
if defined?(ActiveRecord::Base)
ActiveRecord::Base.establish_connection
end
end
before_exec do |server|
ENV["BUNDLE_GEMFILE"] = "#{app_path}/current/Gemfile"
end
其中worker_processes
跟你主机的cpu核数保持一致就好了。其他的不用改。官方也提供了样板文件,我也是参考样板文件作修改的。
现在就可以部署了。
mina deploy
现在可以进入部署的主机,查看部署目录下的shared目录下的tmp/sockets
目录是不是生成了unicorn.sock文件。
2.2 nginx
现在unicorn跑起来,还需要一个接口把nginx反向代理到unicorn,这个通过配置nginx就好了。
在/etc/nginx/conf.d
下新增一个配置文件,比如叫rails.conf。
upstream rails365 {
# Path to Unicorn SOCK file, as defined previously
server unix:///home/yinsigan/rails365/shared/tmp/sockets/unicorn.sock fail_timeout=0;
}
server {
listen 80 default_server;
server_name www.rails365.net;
root /home/yinsigan/rails365/current/public;
keepalive_timeout 70;
location ~ ^/assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri @rails365;
location @rails365 {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://rails365;
}
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 80;
server_name rails365.net;
return 301 $scheme://www.rails365.net$request_uri;
}
关键是反向代理的那部分,就是try_files
和location @rails365
还有upstream rails365
这几个地方。
我部署到的目录是/home/yinsigan/rails365
,root
,还有socket的位置都要指向正确的。
最后执行以下命令让配置生效。
sudo nginx -s reload
现在可以尝试访问你的网站看是否生效了。
另外,关于nginx的配置可以查看本站的相关文档。
完结。
本站帖子均为原创内容,如需转载请注明出处,谢谢。
© 汕尾市求知科技有限公司 | 粤ICP备19038915号 | 在线学员:88
Top