0

デプロイスクリプトでは、次のスニペットを使用してユニコーンを再起動します。

desc "Zero downtime restart of Unicorn"
task :restart do
  run "kill -s USR2 unicorn_pid"
end

マスタープロセスはフォークし、新しいワーカーを開始してから、古いワーカーを強制終了します。しかし今では、新しいマスターが古いマスターを殺し、新しい子が完全に稼働するに新しい接続を引き継ぐようです。新しいワーカーを使用してアプリのプリロードを無効にしpreload_app falseたため、開始に約30〜60秒かかります。この間、新しい接続/Webサイトがハングします。これを回避するにはどうすればよいので、新しいマスターを作成するのは、新しい子が完全に稼働し、リクエストをサーバーする準備ができたときにのみ引き継ぐのでしょうか。:)

アップデート:

私のunicorn.rbは次のようになります。

# name of application
application = "myapp"

# environment specific stuff
case ENV["RAILS_ENV"]
when "integration", "staging"
  worker_processes 1
when "production"
  worker_processes 4
else
  raise "Invalid runtime environment '#{ENV["RAILS_ENV"]}'"
end

# set directories
base_dir = "/srv/#{application}/current"
shared_path = "/srv/#{application}/shared"
working_directory base_dir

# maximum runtime of requests
timeout 300

# multiple listen directives are allowed
listen "#{shared_path}/unicorn.sock", :backlog => 64

# location of pid file
pid "#{shared_path}/pids/unicorn.pid"

# location of log files
stdout_path "#{shared_path}/log/unicorn.log"
stderr_path "#{shared_path}/log/unicorn.err"

# combine REE with "preload_app true" for memory savings
# http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
preload_app false
if GC.respond_to?(:copy_on_write_friendly=)
  GC.copy_on_write_friendly = true
end

before_exec do |server|
  # see http://unicorn.bogomips.org/Sandbox.html
  ENV["BUNDLE_GEMFILE"] = "#{base_dir}/Gemfile"
end

before_fork do |server, worker|
  # the following is highly recomended for "preload_app true"
  if defined?(ActiveRecord::Base)
    ActiveRecord::Base.connection.disconnect!
  end
  if defined?(Sequel::Model)
    Sequel::DATABASES.each{ |db| db.disconnect }
  end

  # This allows a new master process to incrementally
  # phase out the old master process with SIGTTOU to avoid a
  # thundering herd (especially in the "preload_app false" case)
  # when doing a transparent upgrade. The last worker spawned
  # will then kill off the old master process with a SIGQUIT.
  old_pid = "#{server.config[:pid]}.oldbin"
  if old_pid != server.pid
    begin
      sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
      Process.kill(sig, 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

child_ready主な問題はフックがないことだと思います。before_forkとはafter_hook「早すぎる」と呼ばれます。after_forkフックにロジックを追加して、子供がいつ準備ができているかを何らかの方法で検出できると思います...しかし、もっと簡単な解決策があるといいのですが?:)

4

0 に答える 0