Search code examples
ruby-on-railsrubyunicorn

Unicorn - zero downtime using HUP?


I'm confused about what is required to have zero downtime with unicorn, more specifically if it has nothing to do with the preload_app option. I know that if I have preload_app false, I can simply send a HUP signal and unicorn will automatically take into consideration new code, but will it do it in a zero dowtime fashion?

Also, If memory isn't an issue, do I need to use preload_app true at all?

Finally, I see a lot of examples where there is a big before fork block with code about an oldpid. When is this code required?

Thank you


Solution

  • The way I have it set up is to use something like kill -USR2 $(cat /path/to/unicorn.pid) when restarting the unicorn server, and in my unicorn server config, something like this (based on http://unicorn.bogomips.org/examples/unicorn.conf.rb):

    # feel free to point this anywhere accessible on the filesystem
    pid "#{shared_path}/pids/unicorn.pid"
    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
      defined?(ActiveRecord::Base) and
      ActiveRecord::Base.connection.disconnect!
    
      # 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
        end
      end
    end
    

    This will start up the new workers and and gradually switch off the old ones.