Honeybadger पर हम अपने प्रोसेसिंग पाइपलाइन में Sidekiq पर बहुत अधिक निर्भर हैं। हम जो कुछ भी करते हैं वह किसी न किसी बिंदु पर एक कतार के माध्यम से चलता है। परिणामस्वरूप, मैं यह सुनिश्चित करना चाहता हूं कि हम Sidekiq को अच्छी तरह से चला रहे हैं। EC2 पर हमारे हालिया कदम के साथ, हम लंबे समय तक चलने वाले सर्वरों के एक स्थिर सेट से अपने जॉब्स चलाने वाले इंस्टेंसेज के एक सदाबदल सेट पर चले गए। इसने मुझे यह फिर से देखने के लिए प्रेरित किया कि हम बूट समय पर Sidekiq को कैसे शुरू करते हैं, क्योंकि यह पहले की तुलना में अब बहुत अधिक महत्वपूर्ण है।
अतीत में हम सभी वर्कर प्रोसेसेज को स्पिन अप करने के लिए god पर निर्भर थे, क्योंकि हम चाहते थे कि यह उन्हें मॉनिटर करे और उनको समाप्त करे जो बहुत अधिक मेमोरी का उपयोग करते थे। हमारा god कॉन्फिग उन सर्वरों के लिए हाथ से ट्यून किया गया था जिन्हें हमने उन वर्कर्स को चलाने के लिए तैनात किया था। दुर्भाग्य से, मैंने पाया कि systemd का उपयोग करके नए इंस्टेंसेज पर हमारे पुराने god कॉन्फिग को बूट करते समय, हमें कभी-कभी हमारी कॉन्फिगरेशन में निर्दिष्ट से अधिक वर्कर्स चलते हुए मिलते थे। इससे इंस्टेंसेज पर मेमोरी दबाव बढ़ जाता था, जो बुरी खबर थी। इसके साथ कुछ समय तक छेड़छाड़ करने के बाद, और यह महसूस करने के बाद कि हम इसकी अधिकांश कार्यक्षमता का उपयोग नहीं कर रहे थे, मैंने तय किया कि प्रोसेसेज को प्रबंधित करने के लिए god का उपयोग बंद करने का समय आ गया है।
एकाधिक Sidekiq प्रोसेसेज चलाने के लिए एक सरल कमांड
मैं वास्तव में एक स्क्रिप्ट चाहता था जिसे मैं systemd सर्विस के रूप में चला सकूं जो प्रति कोर एक Sidekiq प्रोसेस स्पॉन करे और उन प्रोसेसेज को पुनः आरंभ करे जो बहुत अधिक मेमोरी का उपभोग करते हैं। स्क्रिप्ट को विभिन्न आकारों के EC2 इंस्टेंसेज के साथ काम करने में सक्षम होना चाहिए, क्योंकि कोर की संख्या और RAM की मात्रा भिन्न हो सकती है क्योंकि मैंने यह देखने के लिए विभिन्न इंस्टेंस आकारों की कोशिश की कि हमारे वर्कलोड के लिए सबसे अच्छा क्या काम करेगा। चूंकि मुझे ऐसा कोई स्क्रिप्ट नहीं मिला जो ठीक यही करे, इसलिए मैंने एक लिखा:
बेशक, उस स्क्रिप्ट में थोड़ा उधार लिया गया कोड है। :) process_count मेथड में कोड शायद स्टैक ओवरफ्लो से आता है (मैं इसे वर्षों से अपने यूनिकॉर्न कॉन्फिगरेशन में उपयोग कर रहा हूँ) और fork_child मेथड मूल रूप से sidekiq जेम से sidekiq बिन है।
यह स्क्रिप्ट मौजूद CPU कोर की संख्या के आधार पर कई चाइल्ड प्रोसेसेज को स्पॉन करती है, प्रत्येक चाइल्ड प्रोसेस वही है जैसे आपने सीधे sidekiq कमांड चलाया हो। परिणामस्वरूप, जो भी कमांड-लाइन विकल्प आप इस स्क्रिप्ट को पास करते हैं, वे Sidekiq CLI कोड को पास हो जाएंगे (और उनके द्वारा पार्स किए जाएंगे)। दूसरे शब्दों में, आप इस स्क्रिप्ट को कोई भी विकल्प पास कर सकते हैं जो आप sidekiq को सीधे चलाते समय पास कर सकते हैं, हालांकि कुछ विकल्प (जैसे pid फाइल विकल्प) उपयोग करने का कोई मतलब नहीं है। एक थ्रेड को प्रत्येक चाइल्ड प्रोसेस के मेमोरी उपयोग को समय-समय पर जांचने के लिए भी स्पॉन किया जाता है। यदि कोई चाइल्ड प्रोसेस उपयोग सीमा को पार करता है, तो इसे मार दिया जाता है और इसे बदलने के लिए एक नया प्रोसेस स्पॉन किया जाता है।
क्लस्टर के साथ काम करना
जबकि प्रोसेसेज की संख्या डिफ़ॉल्ट रूप से कोर की संख्या पर सेट होती है (यह मानते हुए कि आप Sidekiq प्रोसेसेज चलाने के लिए एक इंस्टेंस समर्पित कर रहे हैं), आप SK_PROCESS_COUNT एनवायरनमेंट वेरिएबल को स्क्रिप्ट चलाने से पहले सेट करके इसे ओवरराइड कर सकते हैं। इसी तरह, मेमोरी थ्रेशोल्ड इंस्टेंस की कुल RAM के प्रतिशत के रूप में सेट होता है (लाइन 58 पर process_count मान में एक जोड़कर कुछ RAM छोड़कर), लेकिन आप SK_MEMORY_PCT_LIMIT एनवायरनमेंट वेरिएबल के साथ जो भी प्रतिशत चाहते हैं उसे सेट कर सकते हैं। हम इन दो वेरिएबल्स का उपयोग अपने UI को पावर करने वाले Rails ऐप को चलाने वाले इंस्टेंसेज पर Sidekiq प्रोसेसेज की संख्या और मेमोरी उपयोग को प्रतिबंधित करने के लिए करते हैं।
एक अतिरिक्त बोनस के रूप में, यह स्क्रिप्ट आमतौर पर Sidekiq प्रोसेसेज को प्रबंधित करने के लिए उपयोग किए जाने वाले सिग्नल्स को पकड़ती है और उन सिग्नल्स को चाइल्ड प्रोसेसेज पर पास करती है। यह हमें pkill -f -USR1 skcluster का उपयोग करके चाइल्ड प्रोसेसेज को नया काम स्वीकार करना बंद करने की अनुमति देता है (यह हमारे डिप्लॉयमेंट स्क्रिप्ट में एक प्रारंभिक कार्य है), और हम pkill -f skcluster का उपयोग करके सब कुछ समाप्त कर सकते हैं।
Systemd को कॉन्फिगर करना
Systemd सर्विस परिभाषा सीधी है:
चूंकि हम हर इंस्टेंस पर pgbouncer का उपयोग पोस्टग्रेज़ से कनेक्शन प्रॉक्सी करने के लिए करते हैं, हम यह सुनिश्चित करते हैं कि sidekiq प्रोसेसेज बूट होने से पहले pgbouncer सर्विस चल रही है। यदि हम उन्हीं इंस्टेंसेज पर redis चला रहे होते, तो हम Requires और After लाइन्स में redis-server.service भी जोड़ते। EnvironmentFile फाइलनाम से पहले - प्रीफिक्स का उपयोग करके systemd को बताता है कि अगर फाइल मौजूद नहीं है तो यह ठीक है। यह हमें उस फाइल को छोड़ने की अनुमति देता है जब हम डिफ़ॉल्ट प्रोसेस काउंट और मेमोरी लिमिट के साथ जाना चाहते हैं। हम --require विकल्प का उपयोग Sidekiq को यह बताने के लिए करते हैं कि हमारे Rails एप्लिकेशन के कॉन्फिगरेशन और इनिशियलाइज़र्स को लोड करने के लिए कहां जाना है। चूंकि skcluster स्क्रिप्ट SIGTERM को पकड़ती है, हम सभी वर्कर्स को पुनः आरंभ करने के लिए systemctl restart skcluster.service का उपयोग कर सकते हैं (यह हमारे डिप्लॉयमेंट स्क्रिप्ट में एक देर का कार्य है)।
हम कुछ समय से इस स्क्रिप्ट का उपयोग कर रहे हैं, और इसने चैंप की तरह काम किया है। हमें बूट पर बहुत अधिक प्रोसेसेज स्पॉन होने की कोई और समस्या नहीं है, हमारे मॉनिटरिंग से कोई और मेमोरी उपयोग चेतावनी नहीं है, और हम किसी भी प्रकार का EC2 इंस्टेंस लॉन्च कर सकते हैं जो हम चाहते हैं। परेशानी-मुक्त ऑप्स वह ऑप्स है जो मुझे सबसे ज्यादा पसंद है। :)