2008-12-12 11 views
24

मैं fggi (manage.py runfcgi कमांड का उपयोग कर) से जुड़े nginx के पीछे एक django उदाहरण चला रहा हूं। चूंकि कोड मेमोरी में लोड हो गया है, इसलिए मैं django fcgi प्रक्रियाओं को मारने और पुनरारंभ किए बिना नया कोड पुनः लोड नहीं कर सकता, इस प्रकार लाइव वेबसाइट को बाधित कर सकता हूं। खुद को पुनरारंभ करना बहुत तेज़ है। लेकिन एफसीजीआई प्रक्रियाओं को मार कर पहले कुछ उपयोगकर्ताओं के कार्यों में बाधा आ जाएगी जो अच्छा नहीं है। मैं सोच रहा हूं कि बिना किसी रुकावट के मैं नया कोड कैसे पुनः लोड कर सकता हूं। सलाह की अत्यधिक सराहना की जाएगी!nginx के पीछे django चल रहे fcgi को गर्व से कैसे पुनरारंभ करें?

उत्तर

15

मैं एक नए बंदरगाह पर एक नई एफसीजीआई प्रक्रिया शुरू करूंगा, नए पोर्ट का उपयोग करने के लिए nginx कॉन्फ़िगरेशन को बदल सकता हूं, nginx रीलोड कॉन्फ़िगरेशन (जो स्वयं में सुंदर है) है, फिर अंततः पुरानी प्रक्रिया को रोकें (आप नेटस्टैट का उपयोग कर सकते हैं पता लगाएं कि पुराने बंदरगाह का अंतिम कनेक्शन कब बंद है)।

वैकल्पिक रूप से, आप fcgi कार्यान्वयन को एक नई प्रक्रिया को फोर्क करने के लिए बदल सकते हैं, fcgi सर्वर सॉकेट को छोड़कर बच्चे में सभी सॉकेट बंद कर सकते हैं, माता-पिता में fcgi सर्वर सॉकेट बंद कर सकते हैं, बच्चे में एक नई django प्रक्रिया निष्पादित कर सकते हैं (इसे बनाते हुए एफसीजीआई सर्वर सॉकेट का उपयोग करें), और सभी एफसीजीआई कनेक्शन बंद होने के बाद मूल प्रक्रिया को समाप्त कर दें। IOW, runfcgi के लिए सुंदर पुनरारंभ लागू करें।

+1

यदि आप किसी नए पोर्ट पर एक नया एफसीजीआई डालते हैं, तो क्या नई प्रक्रिया में पहले से लॉग इन किए गए उपयोगकर्ताओं को nginx नहीं होगा? यह fcgi प्रक्रिया – Javier

+1

को ठंडा-पुनरारंभ करने जैसा ही होगा, यह वास्तव में सभी उपयोगकर्ताओं को नई प्रक्रिया में अग्रेषित करेगा; इससे कोई नुकसान नहीं होता है। ठंडा-पुनरारंभ करने में समस्या यह है कि चल रही प्रक्रिया मारे जाती है, इसलिए * प्रगति * HTTP अनुरोध विफल हो जाते हैं। यही मामला ओपी चिंतित है (IIUC) –

+0

यह सहायक है। धन्यवाद! – evo

15

तो मैं आगे चला गया और मार्टिन सुझाव लागू होने के बजाय को उत्पन्न करने के लिए उपयोग कर सकते। यहां बैश स्क्रिप्ट है जिसके साथ मैं आया था।

pid_file=/path/to/pidfile 
port_file=/path/to/port_file 
old_pid=`cat $pid_file` 

if [[ -f $port_file ]]; then 
    last_port=`cat $port_file` 
    port_to_use=$(($last_port + 1)) 
else 
    port_to_use=8000 
fi 

# Reset so me don't go up forever 
if [[ $port_to_use -gt 8999 ]]; then 
    port_to_use=8000 
fi 

sed -i "s/$old_port/$port_to_use/g" /path/to/nginx.conf 

python manage.py runfcgi host=127.0.0.1 port=$port_to_use maxchildren=5 maxspare=5 minspare=2 method=prefork pidfile=$pid_file 

echo $port_to_use > $port_file 

kill -HUP `cat /var/run/nginx.pid` 

echo "Sleeping for 5 seconds" 
sleep 5s 

echo "Killing old processes on $last_port, pid $old_pid" 
kill $old_pid 
+0

वाह, सरल अभी तक अविश्वसनीय रूप से उपयोगी। इसे साझा करने के लिए बहुत - बहुत धन्यवाद! – srchulo

10

इस समस्या के समाधान के दौरान मैं इस पृष्ठ पर आया था। बाकी सब कुछ असफल रहा, इसलिए मैंने स्रोत कोड में देखा :)

समाधान बहुत आसान लगता है। Django fcgi सर्वर फ्लूप का उपयोग करता है, जो HUP सिग्नल को उचित तरीके से संभालता है: यह बंद हो जाता है, कृपापूर्वक।

  1. fcgi सर्वर से HUP संकेत (pidfile = runserver का तर्क काम में आ जाएगा)

  2. थोड़ा इंतज़ार (flup बच्चों को संसाधित करता है 10 की अनुमति देता है भेजने: तो तुम सब करने के लिए है सेकंड है, तो कुछ और इंतजार करना है, एक अच्छा नंबर की तरह 15 दिखता है)

  3. fcgi सर्वर से KILL संकेत भेजा है, मामला कुछ बस में यह अवरुद्ध

  4. सर्वर फिर से शुरू

यही है।

+0

यदि आप 'अपस्टार्ट' के तहत अपना django fcgi सर्वर सेट अप करते हैं तो यह वास्तव में अच्छा काम करता है। 'initctl रीलोड ' एचयूपी भेज देगा, और आपकी नौकरी परिभाषा में 'respawn' निर्देश पुन: प्रारंभ करने को संभालेगा। कोई उपद्रव कोई अव्यवस्था नहीं। –

2

हमें अंततः इसका उचित समाधान मिला!

http://rambleon.usebox.net/post/3279121000/how-to-gracefully-restart-django-running-fastcgi

पहले भेजने पुन: प्रारंभ करने का संकेत देने वाला HUP संकेत flup।Flup तो इसके सभी को यह करना होगा:

  1. सॉकेट जो निष्क्रिय बच्चों
  2. बंद हो जाएगा भेजता है एक INT संकेत
  3. 10 सेकंड
  4. इंतजार कर रहा है एक KILL संकेत
भेजता बंद कर देता है

जब सभी बच्चे चले जाते हैं तो यह नए शुरू हो जाएगा।

यह लगभग हर समय काम करता है, सिवाय इसके कि यदि कोई बच्चा अनुरोध करता है कि फ़्लूप निष्पादित करता है 2 तो आपका सर्वर KeyboardInterrupt के साथ मर जाएगा, जिससे उपयोगकर्ता को 500 त्रुटि मिल जाएगी।

समाधान एक सिगिनट हैंडलर स्थापित करना है - विवरण के लिए उपर्युक्त पृष्ठ देखें। सिगिनट को अनदेखा करने से भी आपकी प्रक्रिया 10 सेकंड से बाहर निकलती है जो अधिकांश अनुरोधों के लिए पर्याप्त है।

+0

जैसा कि उस पोस्ट पर टिप्पणियों में उल्लेख किया गया है, यह केवल फ्लुप 1.0.3 के लिए काम करता है। इसके अलावा, मैं इसे prefork के साथ काम नहीं कर सका, केवल थ्रेडेड। – raylu

+0

क्या फ्लैश 1.0.3 का उपयोग न करने में कोई समस्या या विशेष कारण है? मैं इसे प्रीफ़ोर मोड के साथ उपयोग कर रहा हूं और यह ठीक काम करता है। – gingerlime

संबंधित मुद्दे