- Graceful shutdown (सुव्यवस्थित shutdown) वह प्रक्रिया है जिसमें application को termination signal मिलने के बाद नए requests रोकना, मौजूदा requests पूरा करना, और resources साफ़ करना शामिल होता है
- Go में
os/signal package का उपयोग करके SIGINT, SIGTERM जैसे termination signals को सीधे handle किया जा सकता है, और signal.NotifyContext से context-based shutdown control भी संभव है
- HTTP server shutdown के समय
Server.Shutdown() कॉल करने से पहले readiness probe fail कराकर traffic रोकना, फिर कुछ सेकंड इंतज़ार करने के बाद shutdown करना अधिक स्थिर रहता है
- सभी handlers को context shutdown signal पहचानकर बंद हो सकने योग्य होना चाहिए, और
BaseContext या middleware के जरिए इसे एकीकृत रूप से संभाला जा सकता है
- termination signal मिलने के बाद database, message broker, cache जैसे external resources को जानबूझकर साफ़ करना चाहिए, और
defer से register करने पर shutdown order मैनेज करना आसान होता है
Graceful Shutdown क्या है?
- graceful shutdown वह प्रक्रिया है जिसमें application बंद होते समय नए requests रोकना, चल रहे requests के पूरा होने का इंतज़ार करना, और resources साफ़ करना शामिल होता है
- यह लेख मुख्य रूप से HTTP server और container environment पर केंद्रित है, लेकिन यह सभी applications पर लागू होने वाली अवधारणा है
1. Termination signal handling
- Unix-आधारित systems में SIGTERM, SIGINT, SIGHUP जैसे signals termination signals के रूप में उपयोग होते हैं
- Go runtime
SIGTERM, SIGINT मिलने पर default रूप से application बंद कर देता है, लेकिन os/signal.Notify से इन्हें सीधे handle किया जा सकता है
- buffered channel (capacity 1) का उपयोग करने से initialization के दौरान signal खोने से बचा जा सकता है
- Go 1.16 के बाद
signal.NotifyContext का उपयोग करके context-based signal control आसान हो गया है
2. Shutdown time को समझना
- Kubernetes में default रूप से 30 सेकंड की termination grace period दी जाती है (
terminationGracePeriodSeconds)
- सुरक्षित shutdown के लिए 20% margin रखते हुए 25 सेकंड के भीतर shutdown tasks पूरा करना बेहतर माना जाता है
3. नए requests स्वीकार करना बंद करना
http.Server.Shutdown() नए connections रोकता है और मौजूदा requests के पूरा होने तक इंतज़ार करता है
- Kubernetes environment में पहले readiness probe को fail कराया जाता है ताकि traffic आना बंद हो जाए, फिर थोड़ा इंतज़ार करके shutdown किया जाता है
- readiness handler में global variable से shutdown state जांचकर HTTP 503 return करने के लिए configure किया जा सकता है
4. Request processing पूरा करना
- shutdown के लिए इस्तेमाल होने वाले context में उपयुक्त timeout सेट करना ज़रूरी है (
context.WithTimeout)
- shutdown context expire होने पर बचे हुए connections forcefully बंद कर दिए जाते हैं
- सभी handlers को
context.Context का उपयोग करके shutdown signal पहचानने और रुक सकने योग्य बनाकर design करना चाहिए
- इसके लिए middleware या
BaseContext के जरिए सभी requests में shutdown context inject किया जा सकता है
5. Resource cleanup
- termination signal मिलते ही तुरंत resources बंद कर देने से चल रहे handlers में समस्याएँ हो सकती हैं
- shutdown पूरा होने के बाद database connections, message broker, cache आदि को साफ़ करना चाहिए
- Go के
defer का उपयोग करने से initialization के उल्टे क्रम में shutdown routines चलाना संभव होता है, जिससे dependency management आसान हो जाता है
- memory, file descriptor जैसे OS द्वारा अपने-आप साफ़ किए जाने वाले resources के अलावा data flush, transaction rollback जैसे explicit shutdown की आवश्यकता वाले resources भी होते हैं
पूरे उदाहरण का सारांश
signal.NotifyContext से termination signal प्राप्त करना
/healthz readiness endpoint लागू करना
BaseContext से सभी requests में shutdown context inject करना
- readiness के बाद 5 सेकंड इंतज़ार कर shutdown करना
server.Shutdown कॉल fail होने पर forceful shutdown fallback शामिल करना
संदर्भ और संबंधित resources
1 टिप्पणियां
Hacker News की राय
Kubernetes में कभी-कभी load balancer target IP अपडेट होने में काफी समय लगता है। 90% समस्या यह सुनिश्चित करने की होती है कि ट्रैफ़िक वास्तव में drain हो रहा है
log.Fatalइस्तेमाल करने परdeferके अंदर की चीज़ें execute नहीं होतींlog.Fatalos.Exitको कॉल करता है और तुरंत process बंद कर देता हैpanicइस्तेमाल करने परdeferकी सामग्री execute होती हैजब Prometheus
/metricsendpoint को समय-समय पर scrape करता है, तो आखिरी scrape और process shutdown के बीच रिकॉर्ड किए गए metrics propagate नहीं हो सकतेअगर distributed system client के graceful shutdown पर निर्भर करता है, तो system गंभीर रूप से fail हो सकता है
इस बारे में पर्याप्त व्याख्या नहीं है कि जब नया service instance पुराने instance से socket लेता है, तब connection तोड़े बिना application को कैसे restart किया जाए
liveness पर चर्चा कम है
अगर program ctrl c जैसे command को साफ़-सुथरे ढंग से handle नहीं कर पाता, तो वह खराब तरीके से लिखा गया है
Elixir process को छोटे VM processes के रूप में design करता है, इसलिए जानबूझकर graceful shutdown routine बनाने की ज़रूरत नहीं पड़ती
project में graceful shutdown handle करने के लिए एक छोटी library बनाई गई
readiness probe अपडेट करने के बाद कुछ सेकंड इंतज़ार करें ताकि system नए requests भेजना बंद कर दे