Note that there are some explanatory texts on larger screens.

plurals
  1. POZero downtime restart of unicorn/ rails
    primarykey
    data
    text
    <p>In our deploy scripts we use the following snippet to restart unicorn:</p> <pre><code>desc "Zero downtime restart of Unicorn" task :restart do run "kill -s USR2 unicorn_pid" end </code></pre> <p>The master process forks, starts the new workers and then kills the old one. But now it seems the new master kills the old master and takes over any new connections <em>before</em> the new children are fully up. As we disabled preloading of the app using <code>preload_app false</code> the new workers take around 30 - 60 seconds to start. During this time the new connections/ the website hangs. How to avoid this, so making the new master only take over once the new children are fully up and ready to server requests? :)</p> <p>Update:</p> <p>My unicorn.rb looks like this:</p> <pre><code># 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 =&gt; 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) &gt;= 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 </code></pre> <p>I think the main problem is that there's no <code>child_ready</code> hook. The <code>before_fork</code> and <code>after_hook</code> are called "too early". I think I could add some logic in the <code>after_fork</code> hook to somehow detect when a child is ready...but I hope there's an easier solution? :)</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload