3 पॉइंट द्वारा GN⁺ 2025-05-06 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • 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 टिप्पणियां

 
GN⁺ 2025-05-06
Hacker News की राय
  • Kubernetes में कभी-कभी load balancer target IP अपडेट होने में काफी समय लगता है। 90% समस्या यह सुनिश्चित करने की होती है कि ट्रैफ़िक वास्तव में drain हो रहा है

    • global preStop hook में 15 सेकंड का wait time जोड़ने से HTTP 503 ratio में बड़ा सुधार हुआ
    • load balancer deregistration और SIGTERM डिलीवरी के बीच समय बनाकर application handling को सरल किया गया
  • log.Fatal इस्तेमाल करने पर defer के अंदर की चीज़ें execute नहीं होतीं

    • log.Fatal os.Exit को कॉल करता है और तुरंत process बंद कर देता है
    • panic इस्तेमाल करने पर defer की सामग्री execute होती है
  • जब Prometheus /metrics endpoint को समय-समय पर scrape करता है, तो आखिरी scrape और process shutdown के बीच रिकॉर्ड किए गए metrics propagate नहीं हो सकते

    • service बंद होते समय आखिरी कुछ सेकंड के logs खो सकते हैं
    • जब log file को sidecar process monitor कर रहा हो, तब race condition हो सकती है
  • अगर distributed system client के graceful shutdown पर निर्भर करता है, तो system गंभीर रूप से fail हो सकता है

  • इस बारे में पर्याप्त व्याख्या नहीं है कि जब नया service instance पुराने instance से socket लेता है, तब connection तोड़े बिना application को कैसे restart किया जाए

    • systemd में इसे implement करना अपेक्षाकृत आसान है
    • nginx 20 साल से भी ज़्यादा समय से इसे support करता है
    • Kubernetes और Docker इसे support नहीं करते
  • liveness पर चर्चा कम है

    • कई बार ऐसे apps देखे गए हैं जो liveness/readiness के लिए एक ही endpoint इस्तेमाल करते हैं
  • अगर program ctrl c जैसे command को साफ़-सुथरे ढंग से handle नहीं कर पाता, तो वह खराब तरीके से लिखा गया है

  • Elixir process को छोटे VM processes के रूप में design करता है, इसलिए जानबूझकर graceful shutdown routine बनाने की ज़रूरत नहीं पड़ती

  • project में graceful shutdown handle करने के लिए एक छोटी library बनाई गई

    • यह अलग-अलग startup और shutdown mechanisms वाले services को integrate करने के लिए API देती है
  • readiness probe अपडेट करने के बाद कुछ सेकंड इंतज़ार करें ताकि system नए requests भेजना बंद कर दे

    • shutdown हो रहा pod ready state में नहीं होता
    • service endpoint को terminating के रूप में mark करती है
    • SIGTERM के बाद भी एक छोटी window हो सकती है, लेकिन यह बड़ी समस्या नहीं है
    • नए connections स्वीकार किए बिना मौजूदा connections को gracefully बंद करना महत्वपूर्ण है