402v /posts/railsxiang-mu-da-jian-er-di-ge-railsxiang-mu
Rails开发指南 - Nginx+Unicorn的服务器配置
From where:Rails开发指南 - 第一个Rails项目
服务端访问rails项目的实现一般是基于nginx+unicorn,nginx监听80端口,收到对应域的请求之后通过socket或者端口转发给unicorn处理。How unicorn talks to nginx这篇文章把这个转发过程介绍的非常好,建议后续找时间读一下;
#Nginx+Unicorn的服务器配置
一个注意事项是:log、pid等文件的访问权限问题,配置出现问题首先要想到的就是对某个文件是否没有访问权限,后面配置cap也一样。
这部分的内容需要在Mac OSX本地和Ubuntu服务器上都有操作,注意区分当前所在的环境。如Unicorn gem的配置是本地开发之后提交到github上去的,Nginx配置肯定是在服务器上,这里特别强调一下开发的方式:推荐在本地开发,通过git同步代码,服务器上只做git pull。其实在后面的介绍中有了capistrano这个神器之后git pull都省了,完全不需要登录服务器就可以完成网站的发布。
###安装Unicorn
在Gemfile中添加gem 'unicorn',保存退出运行bundle或者bundle install更新gem。
###新建Unicorn配置文件
在config路径下新建unicorn.rb文件,模板内容如下,针对自己的环境做些配置调整,一定要注意访问路径的权限问题,仔细阅读配置文件,如果只是复制粘贴,有任何一条配置不理解的话,以后遇到错误都是要重新阅读查阅的,还不如一次性的都了解清楚。为了叙述上的连贯性,直接在注释部分解释配置目的和注意事项:
# 没有指定环境的话默认在开发环境下运行
env = ENV["RAILS_ENV"] || "development"
# 需要开启的unicorn worker进程数,详见:http://unicorn.bogomips.org/Unicorn/Configurator.html.
worker_processes 4
# app相关设置
# app工作路径,默认向上找两级路径,即projects/config/unicorn.rb
app_dir = File.expand_path("../..", __FILE__)
# 应用名称(项目根目录名)
app_name = "projects"
# 保存unicorn进程id的文件路径,重要,确保当前用户有访问此文件的权限
pid_path = "#{app_dir}/tmp/pids/unicorn.#{app_name}.pid"
# nginx与unicorn进行socket通信的文件路径,重要,确保当前用户有访问此文件的权限
sock_path = "#{app_dir}/tmp/sockets/unicorn.#{app_name}.sock"
# 监听socket文件,也可以在此处指定一个端口号
# 减小backlog的长度以得到更快的速度(这里理解的不深,先把原文留下了:we use a shorter backlog for quicker failover when busy)
listen sock_path, :backlog => 64
# 销毁worker的时间改为30s,默认为60
timeout 30
# 指定pid保存路径
pid pid_path
# Production环境下的特殊配置,即网站发布之后的服务器端配置
if env == "production"
# Help ensure your application will always spawn in the symlinked
# "current" directory that Capistrano sets up.
# 指定production下的工作路径为current,项目自动发布(deploy)到服务器上的时候,capistrano会将当前工作的站点放在current路径下,在后续deploy的时候会详细讲到。
working_directory "#{app_dir}/current"
# production环境下运行的用户和组,确保这个用户有访问app_dir、socket、pid路径的权限
user 'deploy', 'deploy'
# share目录,每次发布时不需要改变或者无法改变的文件会放在这个目录下,如log等,deploy中会讲到
shared_path = "#{app_dir}/current/shared"
# unicorn的错误和输出日志
stderr_path "#{shared_path}/log/unicorn.stderr.log"
stdout_path "#{shared_path}/log/unicorn.stdout.log"
end
# 在创建fork process之前预加载app以得到更快的启动速度,但这样的话必须保证其他的连接(如数据库连接)都被正确的关闭和重启,于是就用到了before_fork和after_fork
preload_app true
# unicorn通过fork processes来实现多进程,因此需要在before_fork和after_fork配置数据库连接的关闭和重启。
before_fork do |server, worker|
# the following is highly recomended for Rails + "preload_app true"
# as there's no need for the master process to hold a connection
if defined?(ActiveRecord::Base)
ActiveRecord::Base.connection.disconnect!
end
# 杀掉位于 .oldbin 这个PID上的master进程.
# deploy的时候很有用,可以实现rails服务的zero downtime重启
old_pid = "#{pid_path}.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|
# the following is *required* for Rails + "preload_app true",
if defined?(ActiveRecord::Base)
ActiveRecord::Base.establish_connection
end
# if preload_app is true, then you may also want to check and
# restart any other shared sockets/descriptors such as Memcached,
# and Redis. TokyoCabinet file handles are safe to reuse
# between any number of forked children (assuming your kernel
# correctly implements pread()/pwrite() system calls)
end
###启动Unicorn 启动Unicorn的方式有几种:
-
在服务端命令行手动启动和停止,伪代码如下:
# 启动unicorn cd #{current_path} && #{fetch(:unicorn_binary)} -c #{fetch(:unicorn_config)} -E #{fetch(:rails_env)} -D # 关闭unicorn kill `cat #{fetch(:unicorn_pid)}` -
生成一个unicorn的服务放在
/etc/init.d下,通过service unicorn_appname start等命令控制unicorn进程。-
运行
sudo vi /etc/init.d/unicorn_appname创建shell文件, -
在文件内指定服务的参数,shell文件的具体内容参见这里
-
权限配置
sudo chmod 755 /etc/init.d/unicorn_appname sudo update-rc.d unicorn_appname defaults -
之后就可以运行start、stop、restart等命令运行unicorn了。
sudo service unicorn_appname start
-
-
最后一种方式也是最实用的方式是启动unicorn的操作放到capistrano或者mina等自动化发布工具上去做,也是本文所采用的方式,后面在讲capistrano的deploy配置时会详细说。
###Nginx配置 nginx的目录配置(如:site-avaliables、site-enables)可以参见:Ghost博客搭建系列之三 - 多重域名访问b,这里默认本地nginx畅通,那么我们需要做的是添加一个nginx配置文件,内容如下(具体说明在注释中):
upstream app {
# unicorn.rb中设置的unicorn的socket文件路径 unix:/home/deploy/apps/projects/current/tmp/sockets/unicorn.projects.sock fail_timeout=0;
}
server {
listen 80;
server_name {my-domain}.com www.{my-domain}.com;
# rails的public文件路径
root /home/deploy/apps/{my-app}/current/public;
try_files $uri/index.html $uri @app;
# location到app这个upstream
location @app {
proxy_pass http://app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
# 资源路径
location ~ ^/assets/ {
expires 1y;
add_header Cache-Control public;
add_header ETag "";
break;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
配置成功后重启nginx:service nginx restart,如果发生错误运行nginx -t快速测试查看原因。
这个时候如果nginx的root对应路径有项目文件的话,运行unicorn已经可以访问到网站。
可以先git clone一个项目到
/home/deploy/apps/{my-app}/current/public,手动启动unicorn测试一下效果。或者直接阅读下面的Cap自动化部署。
#参考连接 3. Nginx:worker_connections are not enough while connecting to upstream
Where to go:Rails开发指南 - Capistrano 3实现Rails自动化部署
评论 · 0
还没有评论。