Last active
August 29, 2015 14:07
-
-
Save jurikern/5f9c8fbb41da6e2ee977 to your computer and use it in GitHub Desktop.
Unicorn task for zero downtime deployment
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace :load do | |
task :defaults do | |
set :pids_dir, -> { File.join(current_path, 'tmp', 'pids') } | |
set :unicorn_pid, -> { File.join(fetch(:pids_dir), "unicorn.pid") } | |
set :unicorn_config_path, -> { File.join(current_path, "config", "unicorn", "#{fetch(:rails_env)}.rb") } | |
set :unicorn_roles, -> { :app } | |
set :unicorn_options, -> { "" } | |
set :unicorn_rack_env, -> { fetch(:rails_env) == "development" ? "development" : "deployment" } | |
set :unicorn_restart_sleep_time, 3 | |
end | |
end | |
namespace :unicorn do | |
desc "Start Unicorn" | |
task :start do | |
on roles(fetch(:unicorn_roles)) do | |
within current_path do | |
if test("[ -e #{fetch(:unicorn_pid)} ] && kill -0 #{pid}") | |
info "unicorn is running..." | |
else | |
with rails_env: fetch(:rails_env) do | |
cmd = <<-EOS | |
bundle exec unicorn | |
-c #{fetch(:unicorn_config_path)} | |
-E #{fetch(:unicorn_rack_env)} | |
-D #{fetch(:unicorn_options)} | |
EOS | |
begin RuntimeError | |
execute cmd | |
rescue | |
execute "if [[ ! -e #{fetch(:pids_dir)} ]]; then mkdir -p #{fetch(:pids_dir)}; fi" | |
execute "ps aux | grep 'unicorn master' | awk '{print $2}' | xargs sudo kill -9" | |
execute cmd | |
end | |
end | |
end | |
end | |
end | |
end | |
desc "Stop Unicorn (QUIT)" | |
task :stop do | |
on roles(fetch(:unicorn_roles)) do | |
within current_path do | |
if test("[ -e #{fetch(:unicorn_pid)} ]") | |
if test("kill -0 #{pid}") | |
info "stopping unicorn..." | |
execute :kill, "-s QUIT", pid | |
else | |
info "cleaning up dead unicorn pid..." | |
execute :rm, fetch(:unicorn_pid) | |
end | |
else | |
info "unicorn is not running..." | |
end | |
end | |
end | |
end | |
desc "Reload Unicorn (HUP); use this when preload_app: false" | |
task :reload do | |
invoke "unicorn:start" | |
on roles(fetch(:unicorn_roles)) do | |
within current_path do | |
info "reloading..." | |
execute :kill, "-s HUP", pid | |
end | |
end | |
end | |
desc "Restart Unicorn (USR2); use this when preload_app: true" | |
task :restart do | |
invoke "unicorn:start" | |
on roles(fetch(:unicorn_roles)) do | |
within current_path do | |
info "unicorn restarting..." | |
execute :kill, "-s USR2", pid | |
end | |
end | |
end | |
desc "Duplicate Unicorn; alias of unicorn:restart" | |
task :duplicate do | |
invoke "unicorn:restart" | |
end | |
desc "Legacy Restart (USR2 + QUIT); use this when preload_app: true and oldbin pid needs cleanup" | |
task :legacy_restart do | |
invoke "unicorn:restart" | |
on roles(fetch(:unicorn_roles)) do | |
within current_path do | |
execute :sleep, fetch(:unicorn_restart_sleep_time) | |
if test("[ -e #{fetch(:unicorn_pid)}.oldbin ]") | |
execute :kill, "-s QUIT", pid_oldbin | |
end | |
end | |
end | |
end | |
desc "Add a worker (TTIN)" | |
task :add_worker do | |
on roles(fetch(:unicorn_roles)) do | |
within current_path do | |
info "adding worker" | |
execute :kill, "-s TTIN", pid | |
end | |
end | |
end | |
desc "Remove a worker (TTOU)" | |
task :remove_worker do | |
on roles(fetch(:unicorn_roles)) do | |
within current_path do | |
info "removing worker" | |
execute :kill, "-s TTOU", pid | |
end | |
end | |
end | |
end | |
def pid | |
"`cat #{fetch(:unicorn_pid)}`" | |
end | |
def pid_oldbin | |
"`cat #{fetch(:unicorn_pid)}.oldbin`" | |
end | |
# config.ru Based an 2 workers for 1GB RAM, 1-core system | |
if defined?(Unicorn) | |
require "unicorn/worker_killer" | |
use Unicorn::WorkerKiller::Oom, (350*(1024**2)), (400*(1024**2)) | |
end | |
# startup options | |
crontab -e | |
@reboot /bin/bash -l -c "cd /app_path/current && ( RAILS_ENV=production bundle exec unicorn -c /app_path/current/config/unicorn/production.rb -E deployment -D )" | |
# Results: | |
# 101msec/request average rate, 10000 requests in minute, 0% errors rate |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment