2012-04-03 7 views
8

पूरे जेवीएम को पुनरारंभ किए बिना उत्पादन कोड को नए कोड को धक्का देने का सबसे अच्छा तरीका क्या है?उत्पादन रिंग-क्लोजर सर्वर पर कोड लोड करना

वर्तमान में मैं उत्पादन में रैप-रीलोड का उपयोग करता हूं, लेकिन यह मेरे लिए काफी काम नहीं करता है क्योंकि कभी-कभी मैं नए कोड के साथ रिंग शुरू करने के अनुरोध से पहले प्रतिलिपि (उदाहरण के लिए डेटाबेस माइग्रेशन कर रहा हूं) में कमांड चलाने के लिए चाहता हूं। इसके अलावा विभिन्न ब्लॉग और ट्यूटोरियल भी उत्पादन में रैप-रीलोड का उपयोग नहीं करते हैं, हालांकि मुझे समझ में नहीं आता कि क्यों नहीं।

मैं निम्नलिखित समाधान के साथ आया हूं, लेकिन मैं कबूल करता हूं कि मुझे हुड के नीचे क्या हो रहा है इसकी गहरी समझ नहीं है। मैं सोच रहा था कि क्या मैं किसी ऐसे व्यक्ति द्वारा स्वच्छता जांच प्राप्त कर सकता हूं जो करता है। क्या यह तकनीक उचित प्रतीत होती है?

विचार एक पथ (/ admin/reload-clj) होना है जो सभी क्लोजर कोड को पुनः लोड करने का कारण बनता है।

(defonce ^:dynamic *jetty*) 
(declare reload-clj) 

(defn app [req] 
... 
(when (= (req :uri) "/admin/reload-clj") (reload-clj req)) 
...) 

(defn start-jetty [] 
(let [j (run-jetty app {:port (http-port) :join? false :max-threads 16})] 
    (dosync (ref-set *jetty* j)) 
    j)) 

(defn reload-clj [req] 
(future 
    (log/info "Reloading clojure code...") 
    (require '(whrusrv admin main utils wdb) :reload-all) 
    (.stop @*jetty*) 
    (start-jetty) 
    (log/info "Clojure reload success!")) 
{:status 200 
    :headers {"Content-Type" "text/plain"} 
    :body "Reloading..."}) 

(defn -main [& args] 
(start-jetty)) 

उत्तर

6

आपके पास जो कोड होगा, वह आपको काम करेगा, हालांकि आपको पता होना चाहिए कि :reload-all केवल नामस्थान लोड करता है और नामस्थान निर्भरताएं लोड करता है। यह उन नामस्थानों की निर्भरता लोड नहीं करता है।

मुझे यह जोड़ना चाहिए कि इस तरह से पुनः लोड करना उत्पादन प्रणाली में दृढ़ता से नहीं है।

नए तैनात कोड में त्रुटियां हो सकती हैं जो सिस्टम को पुनरारंभ होने तक स्पष्ट नहीं हैं (उदाहरण के लिए, वे एक var पर निर्भर करते हैं जो अभी भी चल रहे सिस्टम से परिभाषित है लेकिन जिसका घोषणा हटा दी गई थी)। सिस्टम ठीक काम करेगा लेकिन फिर पुनरारंभ करने में विफल रहता है।

लोड हो रहा कोड भी दुष्प्रभाव हो सकता है जो आपके उत्पादन वातावरण को खराब कर सकता है। यद्यपि इन्हें टालने के लिए इसकी अच्छी शैली है, वास्तव में यह सुनिश्चित करने का एकमात्र तरीका यह है कि अप्रत्याशित कुछ ऐसा नहीं होगा जो एक JVM पुनरारंभ करना है।

जेवीएम पर शून्य-डाउनटाइम परिनियोजन करने का सबसे अच्छा तरीका लोड बैलेंसर का उपयोग करके एक रोलिंग तैनाती है।

+1

स्पष्टीकरण के लिए धन्यवाद, जो चीजों को साफ़ करता है! –

2

मैं एक पिछले काम पर आम तुतलाना में एक इंट्रानेट वेब सेवा के लिए किया था, ताकि अगर उत्पादन के रूप में उत्तीर्ण मैं नहीं जानता। इसके अलावा, सीएल में मेरा जवाब न तो अंगूठी और न ही क्लोजर विशिष्ट है। फिर भी, यह कोड पुनः लोड करने के लिए उपयोगी है।

मैंने जो किया वह उत्पादन lisp उदाहरण पर एक swank सर्वर (कीचड़ का हिस्सा) शुरू करने के लिए है और इसे अपने डेस्कटॉप से ​​भी दूरस्थ रूप से कनेक्ट करें। इस तरह से मैं नया कोड लिख सकता हूं, कोड, डीबग, रीलोड इत्यादि लिख सकता हूं। जाहिर है आपको वास्तविक उत्पादन प्रणाली में अतिरिक्त सावधान रहना होगा।

आप क्लोजर में भी ऐसा ही कर सकते हैं, आपके पास nrepl जैसे swank के विकल्प भी हैं।

आपको खाते में भी सुरक्षा लेनी होगी और केवल स्थानीय कनेक्शन, या आपके लिए जो भी काम करता है, उसे अनुमति देना होगा।

+0

मुझे वैकल्पिक समाधानों में भी बहुत दिलचस्पी है। मुझे लगता है कि जावा में आपके पास क्या कुछ भी बेहतर होगा (ओएसजीआई कोई भी?) – ivant

+0

मैं अपने मध्य-स्तरीय जावा सर्वर के लिए कुछ ऐसा करता हूं। मैं जेएमएक्स के साथ संयोजन में प्रतिलिपि बनाने की कोशिश कर रहा हूं। मुझे लगता है कि कुछ चालबाजी के साथ जेएमएक्स के माध्यम से सभी nrepl यातायात को रूट करना संभव होना चाहिए, जिसमें क्रम में एसएसएल और प्रमाणीकरण के साथ संरक्षित किया जा सकता है। –

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