रीट्राय पॉलिसी — नियमों का एक सेट जो यह निर्धारित करता है कि मोबाइल एप्लिकेशन स्वचालित रूप से विफल नेटवर्क कॉल को कब और कैसे दोहराता है। अस्थिर कनेक्शन या अस्थायी सर्वर त्रुटियों के साथ, एक अच्छी तरह से डिज़ाइन की गई रीट्राय पॉलिसी उपयोगकर्ता के हस्तक्षेप के बिना एप्लिकेशन की विश्वसनीयता में सुधार करती है। Google Developer Relations (2025) के शोध के अनुसार, सही रीट्राय पॉलिसी कार्यान्वयन बार-बार नेटवर्क संचालन वाले मोबाइल एप्लिकेशन में खोए हुए अनुरोधों के प्रतिशत को 40–60% तक कम कर देता है।
मुख्य बातें
रीट्राय पॉलिसी — एक सॉफ़्टवेयर रणनीति है जो नेटवर्क अनुरोध विफलता पर क्लाइंट व्यवहार को परिभाषित करती है: कौन सी त्रुटियाँ दोहराई जानी चाहिए, कितनी बार, किस देरी से, और प्रयास कब बंद करने चाहिए। मोबाइल एप्लिकेशन में, मोबाइल नेटवर्क की अस्थिरता और संभावित अस्थायी सर्वर-साइड विफलताओं के कारण रीट्राय पॉलिसी अत्यंत महत्वपूर्ण है।
एक बुनियादी रीट्राय पॉलिसी में तीन पैरामीटर शामिल हैं: अधिकतम संख्या रीट्राय (maxRetries), प्रारंभिक देरी (baseDelay), और बैकऑफ़ रणनीति। इसके अतिरिक्त, HTTP स्थिति कोड की एक सूची निर्दिष्ट की जा सकती है जिस पर रीट्राय के साथ प्रतिक्रिया देनी चाहिए, और सभी प्रयासों को रोकने के लिए एक टाइमआउट।
मार्टिन क्लेपमैन की पुस्तक “Designing Data-Intensive Applications” के अनुसार, वितरित प्रणालियों में 50% विफलताएँ अस्थायी होती हैं और रीट्राय द्वारा हल की जाती हैं। यह रीट्राय पॉलिसी को सर्वर आर्किटेक्चर में बदलाव किए बिना मोबाइल एप्लिकेशन की दोष सहनशीलता में सुधार करने के सबसे प्रभावी और सस्ते तरीकों में से एक बनाता है।
अस्थायी त्रुटियाँ (रीट्रिएबल) — एकमात्र प्रकार की विफलता जिस पर रीट्राय पॉलिसी को प्रतिक्रिया देनी चाहिए। इनमें कनेक्शन टाइमआउट (SocketTimeoutException), अस्थायी सर्वर अनुपलब्धता (HTTP 503, 502), और DNS त्रुटियाँ शामिल हैं। स्थायी त्रुटियाँ — HTTP 400, 401, 403, 404 — को दोहराना व्यर्थ है क्योंकि वे नेटवर्क या सर्वर में नहीं, बल्कि अनुरोध में समस्या का संकेत देती हैं।
AWS Architecture Blog के शोध के अनुसार, त्रुटियों का रीट्रिएबल और नॉन-रीट्रिएबल में सही वर्गीकरण रीट्राय पॉलिसी डिज़ाइन करते समय सबसे महत्वपूर्ण निर्णय है। HTTP 401 पर एक नॉन-आइडेम्पोटेंट अनुरोध को दोहराने से खाता लॉकआउट हो सकता है, और HTTP 400 को दोहराने से डुप्लिकेट डेटा बन सकता है। हमेशा रीट्राय के लिए कोड की सूची स्पष्ट रूप से कॉन्फ़िगर करें।
फिक्स्ड इंटरवल — सबसे सरल रणनीति: प्रत्येक रीट्राय समान समय अंतराल के बाद होता है। उदाहरण के लिए, 2 सेकंड की देरी के साथ, एप्लिकेशन 2, 2, 2 सेकंड के बाद अनुरोध दोहराता है। फिक्स्ड इंटरवल लागू करने में सरल और पूर्वानुमेय है, लेकिन सामूहिक विफलताओं के दौरान सर्वर पर समान भार बनाता है।
इन्क्रीमेंटल इंटरवल — प्रत्येक रीट्राय के साथ देरी रैखिक रूप से बढ़ती है: पहला रीट्राय 1 सेकंड के बाद, दूसरा 2 के बाद, तीसरा 3 के बाद, इत्यादि। यह रणनीति बार-बार विफलताओं पर सर्वर को ठीक होने के लिए अधिक समय देती है, लेकिन फिर भी एक साथ विफल होने वाले कई क्लाइंट के लिए पूर्वानुमेय है।
| रणनीति | देरी सूत्र | संचयी समय (3 प्रयास) | उपयोग |
|---|---|---|---|
| फिक्स्ड | delay = D | 3 × D | सरल परिदृश्य, स्थानीय टाइमआउट |
| इन्क्रीमेंटल | delay = N × D | 6 × D | क्रमिक भार कमी |
| एक्सपोनेंशियल | delay = D × 2^N | 7 × D | सामूहिक विफलताएँ, क्लाउड सेवाएँ |
| एक्सपोनेंशियल + जिटर | delay = random(0, D × 2^N) | परिवर्तनीय | उच्च भार, माइक्रोसर्विसेज़ |
रणनीति का चुनाव एप्लिकेशन की प्रकृति पर निर्भर करता है। मोबाइल उपकरणों पर डेटा सिंक्रोनाइज़ेशन के बैकग्राउंड कार्यों के लिए, जिटर के साथ एक्सपोनेंशियल रणनीति इष्टतम है — यह सर्वर और उपयोगकर्ता डिवाइस पर न्यूनतम भार के साथ सफलता की उच्चतम संभावना प्रदान करती है।
एक्सपोनेंशियल बैकऑफ़ — एक रणनीति जिसमें प्रत्येक प्रयास के साथ रीट्राय के बीच की देरी दोगुनी हो जाती है। यदि प्रारंभिक देरी 1 सेकंड है, तो देरी का क्रम 1, 2, 4, 8, 16 सेकंड होगा। यह सर्वर को ठीक होने के लिए तेज़ी से बढ़ता समय देता है।
जिटर — एक यादृच्छिक देरी विचलन जो कई क्लाइंट से एक साथ रीट्राय अनुरोधों को रोकता है (थंडरिंग हर्ड समस्या)। जिटर के बिना, एक ही रीट्राय पॉलिसी वाले हज़ार क्लाइंट एक साथ अनुरोध दोहराएँगे, जिससे सर्वर पर पीक लोड बनेगा। जिटर रीट्राय को समय पर फैलाता है।
Kotlin कोरूटीन मुख्य थ्रेड को ब्लॉक किए बिना जिटर के साथ एक्सपोनेंशियल बैकऑफ़ लागू करने की अनुमति देते हैं। kotlinx-coroutines का retry फ़ंक्शन रीट्राय शर्त और अनुरोध निकाय के साथ एक ब्लॉक लेता है, स्वचालित रूप से देरी और प्रयास संख्याओं का प्रबंधन करता है।
suspend fun RetryPolicy.executeWithRetry(
block: suspend () -> Result<T>
): Result<T> {
var lastError: Throwable? = null
repeat(maxRetries + 1) { attempt ->
try {
return block()
} catch (e: Exception) {
if (!isRetriable(e) || attempt == maxRetries) {
return Result.failure(e)
}
val delay = (baseDelayMs * (1 shl attempt))
.toLong()
val jitteredDelay = (delay * (0.5 + Random.nextDouble())).toLong()
delay(jitteredDelay)
lastError = e
}
}
return Result.failure(lastError!!)
}
executeWithRetry फ़ंक्शन नेटवर्क कॉल के साथ एक लैम्ब्डा लेता है और इसे एक्सपोनेंशियल बैकऑफ़ और जिटर के साथ निष्पादित करता है। यदि त्रुटि रीट्रिएबल नहीं है या अधिकतम प्रयास संख्या पार हो गई है, तो फ़ंक्शन एक त्रुटि लौटाता है। रीट्राय के समान वितरण के लिए देरी को 0.5 से 1.5 के यादृच्छिक कारक से गुणा किया जाता है।
सर्किट ब्रेकर — एक डिज़ाइन पैटर्न जो लंबे समय तक सेवा अनुपलब्धता के दौरान अंतहीन रीट्राय अनुरोधों को रोकता है। जब त्रुटि संख्या एक सीमा से अधिक हो जाती है, तो सर्किट ब्रेकर OPEN स्थिति में परिवर्तित हो जाता है और अनुरोध निष्पादित किए बिना तुरंत त्रुटि लौटाता है, जिससे सर्वर को ठीक होने का समय मिलता है।
मोबाइल एप्लिकेशन में, सर्किट ब्रेकर विशेष रूप से उपयोगी होता है जब API नियोजित रखरखाव या ऑपरेटर नेटवर्क विफलताओं के कारण अनुपलब्ध हो। इसके बिना, एप्लिकेशन अंतहीन रीट्राय प्रयासों पर बैटरी और ट्रैफ़िक खर्च करेगा, उपयोगकर्ता अनुभव को खराब करेगा और डिवाइस की बैटरी लाइफ कम करेगा।
सर्किट ब्रेकर की तीन स्थितियाँ: CLOSED (सामान्य संचालन, अनुरोध निष्पादित होते हैं), OPEN (विफलता, अनुरोध अवरुद्ध होते हैं), और HALF_OPEN (पुनर्प्राप्ति जाँच के लिए परीक्षण अनुरोध)। OPEN स्थिति में निर्दिष्ट टाइमआउट के बाद, ब्रेकर HALF_OPEN में परिवर्तित होता है और एक अनुरोध निष्पादित करता है — सफलता पर CLOSED पर, विफलता पर OPEN पर लौटता है।
class CircuitBreaker(
private val failureThreshold: Int = 3,
private val timeoutMs: Long = 30000
) {
private var state = State.CLOSED
private var failureCount = 0
private var lastFailureTime: Long = 0
suspend fun T.protect(block: suspend () -> T): T {
checkState()
return try {
val result = block()
onSuccess()
result
} catch (e: Exception) {
onFailure()
throw e
}
}
}
Kotlin में सर्किट ब्रेकर कार्यान्वयन में एक त्रुटि काउंटर और एक पुनर्प्राप्ति टाइमर है। protect विधि रैप किए गए अनुरोध को निष्पादित करने से पहले वर्तमान स्थिति की जाँच करती है और विफलताओं पर त्रुटि काउंटर को अपडेट करती है। failureThreshold तक पहुँचने के बाद, timeoutMs समाप्त होने तक सभी अनुरोध तुरंत अस्वीकार कर दिए जाते हैं।
मोबाइल नेटवर्क में ऐसी विशेषताएँ हैं जो रीट्राय पॉलिसी को विशेष रूप से महत्वपूर्ण बनाती हैं। Wi-Fi और मोबाइल डेटा के बीच स्विच करना, मेट्रो और सुरंगों में सिग्नल खोना, ऑपरेटर स्तर पर अस्थायी ब्लॉक — ये सभी परिदृश्य अनुरोध विफलताओं का कारण बनते हैं जिन्हें रीट्राय द्वारा सफलतापूर्वक संभाला जा सकता है।
Android पर, Retrofit लाइब्रेरी और OkHttp Interceptor के माध्यम से एक अंतर्निहित रीट्राय तंत्र प्रदान करते हैं। iOS पर, कार्य URLSessionConfiguration और कस्टम डेलीगेशन के माध्यम से हल किया जाता है। क्रॉस-प्लेटफ़ॉर्म डेवलपमेंट के लिए, Ktor (KMP) कॉन्फ़िगर करने योग्य रणनीतियों के साथ अंतर्निहित रीट्राय समर्थन शामिल करता है।
Combine — रिएक्टिव प्रोग्रामिंग के लिए Apple का फ्रेमवर्क। Combine में retry ऑपरेटर त्रुटि होने पर निर्दिष्ट संख्या में publisher को दोहराता है, लेकिन रीट्राय के बीच देरी कॉन्फ़िगर करने की अनुमति नहीं देता। पूर्ण रीट्राय पॉलिसी के लिए, देरी के साथ catch और flatMap का कस्टम संयोजन उपयोग किया जाता है।
extension Publisher {
func retryWithBackoff(
retries: Int = 3,
baseDelay: TimeInterval = 1.0
) -> AnyPublisher<Output, Failure> {
return self.catch { error -> AnyPublisher in
guard retries > 0 else {
return Fail(error).eraseToAnyPublisher()
}
return Just(())
.delay(for: .seconds(baseDelay), scheduler: DispatchQueue.main)
.flatMap { self.retryWithBackoff(
retries: retries - 1,
baseDelay: baseDelay * 2
) }
.eraseToAnyPublisher()
}
.eraseToAnyPublisher()
}
}
Combine में Publisher के लिए retryWithBackoff एक्सटेंशन घटते काउंटर और दोगुनी देरी के साथ पुनरावर्ती कॉल के माध्यम से एक्सपोनेंशियल बैकऑफ़ लागू करता है। delay ऑपरेटर रीट्राय के बीच विराम बनाता है, जबकि catch त्रुटि को इंटरसेप्ट करता है और तय करता है कि पुनः प्रयास करना है या विफलता लौटानी है।
पहली गलती — आइडेम्पोटेंसी की जाँच किए बिना अनुरोध दोहराना। यदि सर्वर ने एक संसाधन बनाया लेकिन नेटवर्क विफलता के कारण पुष्टि नहीं लौटाई, तो रीट्राय एक डुप्लिकेट बनाएगा। POST अनुरोधों के लिए, हमेशा हेडर में एक आइडेम्पोटेंसी कुंजी (Idempotency-Key) का उपयोग करें या केवल GET, PUT और DELETE के लिए रीट्राय पर स्विच करें।
दूसरी गलती — अनंत रीट्राय। हमेशा एक अधिकतम प्रयास संख्या (मोबाइल एप्लिकेशन के लिए 3–5) और सभी प्रयासों के लिए एक कुल टाइमआउट सेट करें। अनंत रीट्राय बैटरी खत्म करते हैं और सर्वर पर परजीवी भार बनाते हैं, विशेष रूप से डेटाबेस माइग्रेशन या API परिवर्तनों के दौरान।
तीसरी गलती — एप्लिकेशन संदर्भ को अनदेखा करना। यदि उपयोगकर्ता ने एप्लिकेशन बंद कर दिया या बैकग्राउंड में चला गया, तो सक्रिय रीट्राय पॉलिसी को सही ढंग से रद्द किया जाना चाहिए। स्क्रीन बंद होने पर स्वचालित रीट्राय रद्दीकरण के लिए SupervisorScope के साथ कोरूटीन या UI जीवनचक्र के साथ Combine का उपयोग करें।
चौथी गलती — रीट्राय प्रयासों को लॉग नहीं करना। लॉगिंग के बिना, आपको पता नहीं चलेगा कि कितने अनुरोध दोहराए गए, कौन सी त्रुटियाँ हुईं, और आपकी रीट्राय पॉलिसी कितनी प्रभावी है। मेट्रिक्स जोड़ें: रीट्राय संख्या, रीट्राय के बाद सफलता, देरी वितरण। यह डेटा आपके विशिष्ट एप्लिकेशन के लिए इष्टतम रणनीति पैरामीटर ट्यून करने में मदद करेगा।
अक्सर पूछे जाने वाले प्रश्न
अधिकांश परिदृश्यों के लिए रीट्राय की इष्टतम संख्या 3–5 प्रयास है। बैकग्राउंड सिंक्रोनाइज़ेशन के लिए, 5–7 प्रयास स्वीकार्य हैं; इंटरैक्टिव अनुरोधों (जैसे फ़ॉर्म सबमिशन) के लिए, 3 से अधिक नहीं। अधिक संख्या में रीट्राय सफलता की संभावना नहीं बढ़ाते लेकिन उपयोगकर्ता की बैटरी और डेटा ट्रैफ़िक खर्च करते हैं।
एक्सपोनेंशियल बैकऑफ़ — रीट्राय प्रयासों के बीच देरी का दोगुना होना: 1 सेकंड, 2, 4, 8, 16 इत्यादि। यदि सर्वर ओवरलोड है, तो पहले रीट्राय के बीच छोटा विराम इसे जल्दी से प्रतिक्रिया देने की अनुमति देता है, जबकि प्रत्येक बाद के रीट्राय के साथ बढ़ता विराम सर्वर को ठीक होने के लिए अधिक समय देता है।
केवल अस्थायी त्रुटियाँ दोहराएँ: 408 (Request Timeout), 429 (Too Many Requests), 502 (Bad Gateway), 503 (Service Unavailable), 504 (Gateway Timeout)। त्रुटियाँ 4xx (408 और 429 को छोड़कर) क्लाइंट समस्याओं का संकेत देती हैं — उन्हें दोहराना व्यर्थ है और उपयोगकर्ता डेटा के लिए खतरनाक हो सकता है।
रीट्राय पॉलिसी विफलता पर एकल अनुरोध के दोहराव का प्रबंधन करती है। सर्किट ब्रेकर सेवा के साथ कनेक्शन स्थिति का प्रबंधन करता है: त्रुटियाँ जमा होने पर, यह सर्किट खोलता है (OPEN) और नए अनुरोधों को ब्लॉक करता है। रीट्राय व्यक्तिगत कॉल स्तर पर काम करता है, सर्किट ब्रेकर सेवा एकीकरण स्तर पर।
परीक्षण के लिए, नेटवर्क विफलताओं का अनुकरण करने के लिए Android पर NetworkInterceptor (OkHttp) और iOS पर URLProtocol (URLSession) का उपयोग करें। पैरामीटर सेट करें: त्रुटि आवृत्ति, अनुपलब्धता अवधि, और प्रतिक्रिया कोड। MockWebServer (OkHttp) या OHHTTPStubs (iOS) के साथ यूनिट परीक्षण वास्तविक नेटवर्क के बिना रीट्राय तर्क की जाँच करते हैं।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें