生产中的Rails引发502错误

时间:2014-12-27 22:06:22

标签: ruby-on-rails deployment unicorn production rvm-capistrano

我尝试使用以下方法将生产模式下的测试应用程序部署到VPN:

  • Digital Ocean上的新型和干净的水滴
  • Ubuntu 14.10
  • Rails 4.2.0
  • Ruby 2.1.5
  • RVM
  • 的PostgreSQL
  • 独角兽
  • Capistrano 3.2.1
  • Nginx的

我的应用已成功部署,但它投了500.html。

该应用已迁移并在公共目录中获取资产。部署期间和日志中没有错误(production.log,unicorn_error.log,unicorn.log)。我通过ps aux|grep unicorn检查了独角兽的工人,并且有几名工人正在研究它。生产中的Rails控制台也工作,所以与PostgreSQL有连接。

我尝试在本地PC上开始制作我的应用程序并使用rake RAILS_ENV=production assets:precompile

请帮我解决问题。如何检测出问题的原因是什么?是在我的部署代码中还是在服务器的设置中?

Nginx设置 的/ etc / nginx的/位点可用/默认

upstream unicorn {
  server unix:/tmp/unicorn.app.sock fail_timeout=0;
}

server {
        listen 80 default deferred;
        #server_name example.com;
        root /var/www/app/current/public;

        location ^~ /assets/ {
                gzip_static on;
                expires max;
                add_header Cache_Control public;
                #try_files $uri/index.html $uri.html $uri @app;
        }

        try_files $uri/index.html $uri @unicorn;

        location @unicorn {
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_redirect off;
                proxy_pass http://unicorn;
        }
        error_page 500 502 503 504 /500.html;
        keepalive_timeout 10;
}

在Gemfile中我使用

group :development do
  gem 'capistrano', '3.2.1', require: false
  gem 'capistrano-rails', require: false
  gem 'capistrano-bundler', require: false
  gem 'rvm1-capistrano3', require: false
  gem 'capistrano3-unicorn', require: false
end

group :production do
  gem 'unicorn'
end

/config/deploy.rb

set :application, 'app'
set :user, "XXX"

set :scm, :git
#set :branch, ->{ `git rev-parse --abbrev-ref HEAD`.chomp }
set :branch, "master"
set :repo_name, 'deployment'
set :repo_url, ->{ "git@github.com:sfolt/#{fetch :repo_name}.git" }

set :rails_env, fetch(:stage)
set :rvm1_ruby_version, 'ruby-2.1.5'

set :keep_releases, 5
set :format, :pretty
set :use_sudo, false
set :deploy_via, :remote_cache

set :unicorn_conf, "#{deploy_to}/current/config/unicorn.rb"
set :unicorn_pid, "#{deploy_to}/shared/pids/unicorn.pid"
set :bundle_without, [:development, :test]

set :linked_files, %w{
  config/database.yml
  config/secrets.yml
}
set :linked_dirs, %w{log tmp/pids tmp/cache tmp/sockets tmp/sessions}

namespace :assets do
  task :precompile do
    run "cd #{release_path}; rake assets:precompile RAILS_ENV=production"
  end
end

namespace :deploy do
  task :restart do
    run "if [ -f #{unicorn_pid} ] && [ -e /proc/$(cat #{unicorn_pid}) ]; then kill -USR2 `cat #{unicorn_pid}`; else cd #{deploy_to}/current && bundle exec unicorn -c #{unicorn_conf} -E #{rails_env} -D; fi"
  end
  task :start do
    run "bundle exec unicorn -c #{unicorn_conf} -E #{rails_env} -D"
  end
  task :stop do
    run "if [ -f #{unicorn_pid} ] && [ -e /proc/$(cat #{unicorn_pid}) ]; then kill -QUIT `cat #{unicorn_pid}`; fi"
  end
end

after 'deploy:finishing', 'deploy:cleanup'
after 'deploy:publishing', 'unicorn:restart'

/config/deploy/production.rb

set :stage, :production
set :deploy_to, "/var/www/app"

server 'XXX.XXX.XXX.XXX',
  user: 'XXX',
  port: XXX,
  roles: [:app, :web, :db],
  ssh_options: {
    user: 'XXX'
  }

/config/unicorn/production.rb

deploy_to  = "/var/www/app"
rails_root = "#{deploy_to}/current"
pid_file   = "#{deploy_to}/shared/pids/unicorn.pid"
socket_file= "#{deploy_to}/shared/unicorn.sock"
log_file   = "#{rails_root}/log/unicorn.log"
err_log    = "#{rails_root}/log/unicorn_error.log"
old_pid    = pid_file + '.oldbin'

timeout 120
worker_processes 2
listen socket_file, backlog: 1024
pid pid_file
stderr_path err_log
stdout_path log_file

preload_app true

GC.copy_on_write_friendly = true if GC.respond_to?(:copy_on_write_friendly=)

before_exec do |server|
  ENV["BUNDLE_GEMFILE"] = "#{rails_root}/Gemfile"
end

before_fork do |server, worker|
  defined?(ActiveRecord::Base) and
  ActiveRecord::Base.connection.disconnect!

  if File.exists?(old_pid) && server.pid != old_pid
    begin
      Process.kill("QUIT", File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
    end
  end
end

after_fork do |server, worker|
  defined?(ActiveRecord::Base) and
  ActiveRecord::Base.establish_connection
end

1 个答案:

答案 0 :(得分:1)

502错误意味着nginx和你的独角兽进程之间没有通信。

在检查配置文件后,在我看来问题是你设置unicorn来监听这个套接字/var/www/app/shared/unicorn.sock,但你告诉nginx通过这个套接字/tmp/unicorn.app.sock与独角兽进行通信

按如下方式更改upstream文件中的nginx.conf部分可解决此问题:

upstream unicorn {
  server unix:/var/www/app/shared/unicorn.sock fail_timeout=0;
}