2012-11-27 14 views
7
task :restart_unicorn, :except => { :no_release => true } do 
    run "#{try_sudo} kill -s USR2 $(cat /var/www/app_name/shared/pids/unicorn.pid)" 
end 

dağıtmak aşağıdaki eski kod kullanmaya devam eder, ne olur, yeni bir boynuzlu at usta yaratılmış olmasıdır ve eski bir adının (old) eklenen etmiştir. Eski olanı asla öldürmez, ama kendi başıma öldürsem bile, yeni tek boynuzlu at koşulu hala eski kodu benim konuşmamdan önce gösteriyor. Yeni örnek, eskisiyle aynı yaratım zamanına sahiptir - onun sadece kopyalanması gibi. Örneği durdurursam ve tekrar başlatırsam çalışır, ancak sıfır kapalı kalma dağıtımını yapabilmek isterim.

Herhangi bir yardım için teşekkür ederiz.

old_pid = get_pid('/var/www/appname/shared/pids/unicorn.pid') 
run "#{try_sudo} kill -s SIGUSR2 $(cat /var/www/appname/shared/pids/unicorn.pid)" 
/var/www/app/current/tmp/pids/unicorn.pid)" 
run "#{try_sudo} kill -s SIGWINCH #{old_pid}" 

Bu pid üzerinde SIGUSR2 çalışır ve eski boynuzlu at süreci öldürür:

DÜZENLEME

sugest İlya O. izledikten sonra, ben bunu yapan bir capistrano görevi yarattı. Sorun şu ki, tüm uygulama sunucum son zamanlarda dağıtılan koduma hiçbir zaman güncellenmemiştir, bu görev sadece eski tek boynuzlu at ortamımı yeni bir sürece kopyalamak gibi görünüyor. Usta süreci öldürdüğümde ve tekrar tek boynuzlu at yeniden başlasa iyi çalışır, ama sonra bir dakika veya düşmüş istekleri vardır.

cevap

5

Unicorn yapılandırmanızda preload_app true değerine sahip misiniz? Eğer öyleyse, SIGUSR2 ve ardından SIGQUIT'i yeni işlem başlatılıp çalıştırıldıktan sonra orijinal master sürecine göndermeniz gerekir.

Ayrıca, orijinal ana işlemin öldüğü, ancak çocukların hala istekleri karşıladığı da olabilir. SIGUSR2'yi göndermeyi deneyebilir ve yeni ana işlemin ortaya çıkmasından sonra, eski tek boynuzlu çocuk süreçlerini öldürmek için SIGWINCH (eski ustaya) ve eski ana süreçte SIGQUIT (SİGNAM) komutunu gönderin. Artık yalnızca istekleri sunan "yeni" tekboynuzlu süreçlere sahip olmalısınız.

DÜZENLEME: SIGWINCH yerine SIGQUIT yapmayı deneyin. SIGWINCH'den sonra eski sürecin yumurtlama işçileri olabileceğini düşünüyorum.

+0

Evet, 'preload_app' true olarak ayarlandı. Harika bilgi!Tek sorum, eski tek boynuzlu at süreçlerinin ne olduğunu tanımlamanın en iyi yolu nedir? –

+0

.oldbin ya da (eski) eski işlemin ismine eklenecektir, böylece tekdüzen ve eski –

+0

için bir 'grep'ye' ps' baslatabilirsiniz. Şimdiye kadar sunduğun yardım için teşekkürler. –

2

Tek boynuzlu atlı adamlar bunun için halka açık bir init.d betiğine sahipler, muhtemelen bunu sisteminize eklemeniz ve kullanmanız gerekir.

Tek boynuzlu atlamayı yeniden başlatmak için 2 farklı yol bulacaksınız: yeniden başlatma ve yükseltme.

Bu yazıyı /etc/init.d/unicorn dizinine ekleyebilirim, bu yürütülebilir dosyayı ayarlayın, ardından capistrano tarifinizde sudo service unicorn upgrade'u kullanabilirsiniz.

Init komut dosyası: Neden Genellikle böyle capistrano şey, Capistrano'nun üzerinde bütün işleri koyarak emin değilim http://unicorn.bogomips.org/examples/init.sh

+0

Bunun işe yarayacağını düşündüm ama olmadı. –

+0

Yükseltilemedi, 'unicorn -D -c /var/www/appname/current/config/unicorn.rb' yerine ana başlatılamadı, ayrıntıları kontrol etmek için stderr günlüğünü kontrol edin –

+0

stderror şunu gösteriyor: E, [2012- 11-29T23: 04: 45.574813 # 3345] HATA -: dinleyicinin eklenmesi başarısız oldu addr =/tmp/.sock (kullanımda) E, [2012-11-29T23: 04: 45.574938 # 3345] HATA -: yeniden deneniyor 0,5 saniye (4 deneme kaldı) –

3

yeterlidir:

set :unicorn_pid, "unicorn.my_website.pid" 

desc "Zero-downtime restart of Unicorn" 
task :restart, roles: :app do 
    if remote_file_exists?("/tmp/#{unicorn_pid}") 
    puts "Killing /tmp/#{unicorn_pid}" 
    run "kill -s USR2 `cat /tmp/#{unicorn_pid}`" 
    else 
    run "cd #{current_path} ; RAILS_ENV=#{rails_env} bundle exec unicorn_rails -C#{unicorn_config} -D" 
    end 
end 

ve sonra öldürmek için gerçek kod eski boynuzlu at süreç bunu kullanmak

# config/unicorn.rb 

# Set environment to development unless something else is specified 
env = ENV["RAILS_ENV"] || "production" 

# See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete documentation. 
worker_processes 2 # amount of unicorn workers to spin up 

APP_PATH = "/u/apps/my_website/current" 

listen "/tmp/my_website.socket" 

preload_app true 

timeout 30   # restarts workers that hang for 30 seconds 

pid "/tmp/unicorn.my_website.pid" 

# By default, the Unicorn logger will write to stderr. 
# Additionally, ome applications/frameworks log to stderr or stdout, 
# so prevent them from going to /dev/null when daemonized here: 
stderr_path APP_PATH + "/log/unicorn.stderr.log" 
stdout_path APP_PATH + "/log/unicorn.stdout.log" 

if env == "production" 
    # Help ensure your application will always spawn in the symlinked 
    # "current" directory that Capistrano sets up. 
    working_directory APP_PATH 

    # feel free to point this anywhere accessible on the filesystem 
    user 'deploy', 'deploy' # 'user', 'group' 
    shared_path = "/u/apps/my_website/shared" 

    stderr_path "#{shared_path}/log/unicorn.stderr.log" 
    stdout_path "#{shared_path}/log/unicorn.stdout.log" 
end 

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 
    if defined?(ActiveRecord::Base) 
    ActiveRecord::Base.connection.disconnect! 
    end 


    # When sent a USR2, Unicorn will suffix its pidfile with .oldbin and 
    # immediately start loading up a new version of itself (loaded with a new 
    # version of our app). When this new Unicorn is completely loaded 
    # it will begin spawning workers. The first worker spawned will check to 
    # see if an .oldbin pidfile exists. If so, this means we've just booted up 
    # a new Unicorn and need to tell the old one that it can now die. To do so 
    # we send it a QUIT. 
    # 
    # This enables 0 downtime deploys. 
    old_pid = "/tmp/unicorn.my_website.pid.oldbin" 
    if File.exists?(old_pid) && server.pid != old_pid 
    begin 
     Process.kill("QUIT", 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| 

    # Unicorn master loads the app then forks off workers - because of the way 
    # Unix forking works, we need to make sure we aren't using any of the parent's 
    # sockets, e.g. db connection (since "preload_app true") 
    if defined?(ActiveRecord::Base) 
    ActiveRecord::Base.establish_connection 
    end 

    # if preload_app is true, then you may also want to check and 
    # restart any other shared sockets/descriptors such as Memcached, 
    # and Redis. TokyoCabinet file handles are safe to reuse 
    # between any number of forked children (assuming your kernel 
    # correctly implements pread()/pwrite() system calls) 
end 

boynuzlu at yapılandırmasına aslında kurulum çoğu zaman ve başvurum olmadan yeniden olduğunu Herhangi bir sorun, büyük olasılıkla zaten varsayılan yapılandırma, ama zaten bir şey eksik, bu deneyin bir deneyin, tüm zaten var;)

+0

Bu işe geri dönünce ... bir hafta önce başladığım yerde bitti. dinleyici eklenemedi addr =/tmp/.sock (kullanımda) –

+0

Yapılandırmada işaret etmem gereken soketin ne olduğunu anlamıyorum. –

+0

nginx + unicorn kullanıyor musunuz? – rorra