1

我有一个中型 EC2 实例,几天后似乎损坏了独角兽实例,导致应用程序抛出 403 错误,url 显示为http://app/foo/bar

“app”是独角兽的代理。这是我的 nginx 站点配置

    upstream app {
            server unix:/home/foo/app/shared/sockets/unicorn.sock fail_timeout=0;
    }


    server {
            listen   80; # This is on by default. 
            client_max_body_size 2G;
            #       upload_max_file_size 50m;
            server_name foo.tld; # Hostname
            keepalive_timeout 5;
            root /home/foo/app/current/public; # Application root.

            access_log /home/foo/log/foo_access.log; # Logs for nginx access
            error_log /home/foo/log/foo_error.log;

            if ($request_method !~ ^(GET|HEAD|PUT|POST|DELETE|OPTIONS)$) {
                    return 405;
            }

            if (-f $document_root/system/maintenance.html) {
              return 503;
            }

            error_page 503 @maintenance;

            location @maintenance {
              rewrite  ^(.*)$  /system/maintenance.html last;
              break;
            }

            # Static serving as defined in the RoR guides 
            # http://guides.rubyonrails.org/asset_pipeline.html#in-production
            location ~ ^/(assets(?!\/(files|pictures)))/ {
                    gzip_static on;
                    expires max;
                    add_header Cache-Control public;
            }       

            # Proxy forwarding to unicorn
            location / {
                    try_files $uri/index.html $uri.html $uri @app;
                    error_page 404                  /404.html;
                    error_page 422                  /422.html;
                    error_page 500 502 503 504      /500.html;
                    error_page 403                  /403.html;
            }

            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;
            }

        location = /favicon.ico {
                expires max;
                add_header Cache-Control public;
        }

        location ~ \.php {
                deny all;
        }
    }

我的独角兽.rb

worker_processes 4
working_directory '/home/foo/app/current'

# This loads the application in the master process before forking
# worker processes
# Read more about it here:
# http://unicorn.bogomips.org/Unicorn/Configurator.html
preload_app true
GC.respond_to?(:copy_on_write_friendly=) and
  GC.copy_on_write_friendly = true


timeout 30

# This is where we specify the socket.
# We will point the upstream Nginx module to this socket later on
listen '/home/foo/app/shared/sockets/unicorn.sock', :backlog => 64
pid '/home/foo/app/shared/pids/unicorn.pid'

# Set the path of the log files inside the log folder of the testapp
stderr_path '/home/foo/app/current/log/unicorn.stderr.log'
stdout_path '/home/foo/app/current/log/unicorn.stdout.log'

还有我的帽子配方

require 'bundler/capistrano'

set :rvm_ruby_string, ENV['GEM_HOME'].gsub(/.*\//,"") # Read from local system
require "rvm/capistrano"                               # Load RVM's capistrano plugin.

# Application name
set :application, "foo"

# Repo information
set :repository, "foo.git"
set :scm, :git
set :branch, "master"

# Server information
set :user, "foo"
set :scm_passphrase, "foo"
set :deploy_via, :remote_cache
server "foo.tld", :web, :app, :db # This is our EC2 Instance
set :deploy_to, "/home/foo/app"
ssh_options[:keys] = [File.join(ENV["HOME"], "keys/foo")]
set :use_sudo, false

namespace :deploy do

  desc "Restart of Unicorn"
  task :restart, :excerpt => { :no_release => true } do
    run "kill -a USR2 `cat /home/foo/app/shared/pids/unicorn.pid`"
  end

  desc "Start Unicorn"
  task :start, :excerpt => { :no_release => true } do
    run "cd #{current_path} ; bundle exec unicorn_rails -c config/unicorn.rb -E production -D"
  end

  desc "Stop Unicorn"
  task :stop, :excerpt => { :no_release => true } do
    run "kill -s QUIT `cat /home/foo/app/shared/pids/unicorn.pid`"
  end

  namespace :web do
    desc "Throw maintenance page up"
    task :disable do
      require "erb"
      on_rollback { run "rm #{shared_path}/system/maintenance.html" }

      reason = ENV['REASON']
      deadline = ENV['UNTIL']

      template = File.read("./app/views/layouts/maintenance.html.erb")
      result   = ERB.new(template).result(binding)

      put result, "#{shared_path}/system/maintenance.html", :mode => 0644
    end
  end
end

关于为什么独角兽会在几天后采取行动的任何见解?此外,我当前的设置中是否有任何“陷阱”。?

更新:看起来独角兽永远无法重新启动挂起的进程

E, [2012-07-03T09:59:13.554781 #9521] ERROR -- : worker=3 PID:9656 timeout (31s > 30s), killing
E, [2012-07-03T09:59:13.710103 #9521] ERROR -- : reaped #<Process::Status: pid 9656 SIGKILL (signal 9)> worker=3
I, [2012-07-03T09:59:13.710349 #9521]  INFO -- : worker=3 spawning...
I, [2012-07-03T09:59:13.906277 #16214]  INFO -- : worker=3 spawned pid=16214
I, [2012-07-03T09:59:13.906672 #16214]  INFO -- : worker=3 ready
E, [2012-07-03T13:37:45.158213 #9521] ERROR -- : worker=3 PID:16214 timeout (31s > 30s), killing
E, [2012-07-03T13:37:45.402827 #9521] ERROR -- : reaped #<Process::Status: pid 16214 SIGKILL (signal 9)> worker=3
I, [2012-07-03T13:37:45.403125 #9521]  INFO -- : worker=3 spawning...
I, [2012-07-03T13:37:45.531584 #16270]  INFO -- : worker=3 spawned pid=16270
I, [2012-07-03T13:37:45.531982 #16270]  INFO -- : worker=3 ready
4

1 回答 1

2

因为你有 preload_app: true,你需要在 fork 时重新连接你的数据库/缓存实例

在 before_fork

Rails.cache.reset
ActiveRecord::Base.connection.disconnect!

在 after_fork

ActiveRecord::Base.establish_connection Rails.env

如果您有任何其他 memcached/dalli 连接,请确保您也 .reset 它们。祝你好运!

于 2013-06-24T17:20:14.473 回答