2012-11-27 27 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 

तैनात जब मैं सर्वर पर sudo kill -s USR2 $(cat /var/www/app_name/shared/pids/unicorn.pid) कर पुराने कोड निम्न का उपयोग कर रहा है, क्या होता है कि एक नए गेंडा गुरु बनाया जाता है, और पुराने एक (old) अपने नाम के साथ जोड़ दिया गया है। बूढ़ा व्यक्ति कभी नहीं मारा जाता है, लेकिन अगर मैं इसे अपने आप मारता हूं, तो भी नया यूनिकॉर्न इंस्टेंस अभी भी मेरे तैनाती से पहले पुराना कोड दिखा रहा है। नए उदाहरण में पुराने निर्माण के समान ही समय है - जैसे कि इसे सिर्फ डुप्लिकेट किया जा रहा है। अगर मैं इंस्टेंस को रोकता हूं, और इसे फिर से शुरू करता हूं, तो यह काम करता है, लेकिन मैं शून्य-डाउनटाइम तैनाती करने में सक्षम होना चाहता हूं।यूनिकॉर्न + पुनः आरंभ

किसी भी मदद की सराहना की जाती है।

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}" 

इस पीआईडी ​​पर SIGUSR2 चलाता है, और वर्ष गेंडा प्रक्रिया को मारता है:

संपादित

sugest इल्या ओ पालन करने के बाद, मैं एक Capistrano कार्य है कि इस करता है बनाया। समस्या यह है कि मेरा सभी एप्लिकेशन सर्वर कभी भी मेरे हाल ही में तैनात कोड में अपडेट नहीं किया गया है, यह कार्य बस मेरे पुराने यूनिकर्न वातावरण को एक नई प्रक्रिया में कॉपी करने लगता है। यह ठीक काम करता है अगर मैं बस मास्टर प्रक्रिया को मारता हूं और फिर यूनिकॉर्न ताजा फिर से शुरू करता हूं, लेकिन फिर एक मिनट या उससे भी कम अनुरोध किए जाते हैं।

उत्तर

5

क्या आपके पास preload_app आपके यूनिकॉर्न कॉन्फ़िगरेशन में सत्य है? यदि ऐसा है, तो नई प्रक्रिया बढ़ने और चलने के बाद आपको मूल मास्टर प्रक्रिया में SIGUSR2 और फिर SIGQUIT भेजने की आवश्यकता है।

यह भी हो सकता है कि मूल मास्टर प्रक्रिया की मृत्यु हो गई है लेकिन बच्चे अभी भी अनुरोध कर रहे हैं। आप SIGUSR2 भेजने का प्रयास कर सकते हैं, और नई मास्टर प्रक्रिया के बाद, पुरानी यूनिकॉर्न बाल प्रक्रियाओं को मारने के लिए सिगविच (पुराने मास्टर को) भेज दें, और फिर पुरानी मास्टर प्रक्रिया पर सिगक्विट भेजें। अब आपके पास अनुरोधों की सेवा करने वाली केवल "नई" यूनिकॉर्न प्रक्रियाएं होनी चाहिए।

संपादित करें: सिग्विन के बजाय सिग्क्विट करने का प्रयास करें। मुझे लगता है कि सिगविच के बाद पुरानी प्रक्रिया श्रमिकों को जन्म दे सकती है।

+0

हां, 'preload_app' सत्य पर सेट है। महान जानकारी!मेरा एकमात्र सवाल यह है कि पुरानी यूनिकॉर्न प्रक्रिया आईडी क्या है यह पहचानने का सबसे अच्छा तरीका क्या है? –

+0

.oldbin या (पुराने) वर्ष प्रक्रिया के नाम के साथ जोड़ दिया जाएगा ताकि पाइप 'के लिए गेंडा और पुराने –

+0

एक' grep' को ps' मैं एक अद्यतन के साथ ओपी संपादित आप कर सकते थे। अब तक दी गई सहायता के लिए धन्यवाद। –

2

यूनिकॉर्न लोगों के लिए सार्वजनिक init.d स्क्रिप्ट है, तो आपको शायद इसे अपने सिस्टम में जोड़ना चाहिए और इसका उपयोग करना चाहिए।

आपको यूनिकॉर्न को पुनरारंभ करने के 2 अलग-अलग तरीके मिलेंगे: पुनरारंभ करें और अपग्रेड करें।

मैं व्यक्तिगत रूप से इस स्क्रिप्ट को /etc/init.d/unicorn में जोड़ता हूं, यह निष्पादन योग्य सेट करें तो आप अपने कैपिस्ट्रानो रेसिपी में sudo service unicorn upgrade का उपयोग कर सकते हैं।

Init स्क्रिप्ट: http://unicorn.bogomips.org/examples/init.sh

+0

मैंने सोचा कि यह काम करेगा लेकिन यह नहीं था। –

+0

उन्नयन नहीं किया जा सका, शुरू करने 'गेंडा डी -c /var/www/appname/current/config/unicorn.rb' के बजाय मास्टर, शुरू करने के लिए विवरण के लिए stderr लॉग –

+0

stderror इस से पता चलता विफल रहा है: ई, [2012- 11-29T23: 04: 45.574813 # 3345] त्रुटि -: श्रोता जोड़ना addr =/tmp/.sock (उपयोग में) ई, [2012-11-29T23: 04: 45.574938 # 3345] त्रुटि - में पुनः प्रयास करना 0.5 सेकंड (4 की कोशिश करता बाएं) –

3

मुझे यकीन है कि तुम क्यों Capistrano पर सभी कि काम लगा रहे हैं, आम तौर पर इस तरह Capistrano कुछ पर नहीं कर रहा हूँ पर्याप्त है:

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 

और फिर हत्या के लिए वास्तविक कोड वर्ष गेंडा प्रक्रिया गेंडा विन्यास पर वास्तव में है

# 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 

मुझे लगता है कि का उपयोग सेटअप समय के सबसे अधिक और अपने आवेदन के बिना फिर से लोड है कोई भी मुद्दा, आपके पास शायद पहले से ही डिफ़ॉल्ट कॉन्फ़िगरेशन के बाद से सब कुछ है, लेकिन यदि आप कुछ खो रहे हैं, तो इसे आज़माएं;)

+0

इस के लिए वापस जा कोशिश की ... अभी वापस समाप्त हो गया है, जहां मैं एक हफ्ते पहले शुरू कर दिया। श्रोता जोड़ने में addr =/tmp/.sock (उपयोग में) –

+0

मुझे समझ में नहीं आता कि सॉकेट क्या है जिसे मैं कॉन्फ़िगरेशन में इंगित करना चाहता हूं? –

+0

क्या आप nginx + unicorn का उपयोग कर रहे हैं? – rorra