डाउनस्ट्रीम विफलताओं के लिए सर्किट ब्रेकर
opossum-शैली के सर्किट ब्रेकर एकीकरण से सेवाओं को क्रमिक विफलताओं से सुरक्षित रखिए।
डाउनस्ट्रीम विफलताओं के लिए सर्किट ब्रेकर, CoddyKit पर NestJS एंटरप्राइज़ बैकएंड API का एक निःशुल्क पाठ है। यह 4 में से 2वाँ पाठ है। आप नीचे पूरा पाठ निःशुल्क पढ़ सकते हैं—फिर अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर के साथ ब्राउज़र में इसका व्यावहारिक अभ्यास कर सकते हैं। यह NestJS एंटरप्राइज़ बैकएंड API सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। NestJS एंटरप्राइज़ बैकएंड API पाठ्यक्रम में कुल 4 पाठ शामिल हैं।
कैस्केडिंग विफलताएँ क्यों होती हैं
किसी एंटरप्राइज़ NestJS बैकएंड में आपकी सेवा शायद ही कभी अकेले काम करती है। यह भुगतान गेटवे, प्रमाणीकरण प्रदाता, खोज क्लस्टर और अन्य माइक्रोसर्विस को कॉल करती है। जब कोई एक डाउनस्ट्रीम निर्भरता धीमी हो जाती है, तो उस पर प्रतीक्षा कर रहा हर अनुरोध एक कनेक्शन, एक थ्रेड और इवेंट लूप का कुछ हिस्सा रोके रखता है।
- धीमी निर्भरता आपके HTTP कनेक्शन पूल को समाप्त कर देती है।
- लंबित अनुरोध जमा होते जाते हैं और हर जगह विलंबता बढ़ती जाती है।
- आपकी सेवा अस्वस्थ हो जाती है और उसे कॉल करने वाले भी विफल होने लगते हैं।
इस डोमिनो-प्रभाव को कैस्केडिंग विफलता कहते हैं। circuit breaker वह पैटर्न है जो इन डोमिनो को गिरने से रोकता है।
Circuit Breaker की स्टेट मशीन
circuit breaker किसी जोखिमपूर्ण कॉल को लपेटता है और तीन अवस्थाओं के माध्यम से उसकी सेहत पर नज़र रखता है:
- CLOSED — कॉल सामान्य रूप से आगे जाती हैं। विफलताओं की गिनती की जाती है।
- OPEN — बहुत अधिक विफलताएँ हो चुकी हैं; निर्भरता को छुए बिना कॉल तुरंत अस्वीकार कर दी जाती हैं। इससे डाउनस्ट्रीम सेवा को उबरने का समय मिलता है।
- HALF_OPEN — कूलडाउन के बाद कुछ परीक्षण कॉल की अनुमति दी जाती है। यदि वे सफल होती हैं, तो breaker बंद हो जाता है; यदि वे विफल होती हैं, तो यह फिर खुल जाता है।
मुख्य बात यह है: जब breaker OPEN हो, तो हर अनुरोध के लिए टाइमआउट की प्रतीक्षा करने के बजाय तुरंत विफल हों।
शुरू से एक न्यूनतम breaker बनाना
किसी लाइब्रेरी का उपयोग करने से पहले इसकी कार्यप्रणाली समझना उपयोगी होता है। यहाँ TypeScript में एक छोटा, स्वतंत्र breaker दिया गया है, जो लगातार विफलताओं और reset timeout के आधार पर CLOSED और OPEN के बीच बदलता है।
यह स्वतंत्र रूप से चलता है, ताकि आप अवस्थाओं में होने वाले बदलाव देख सकें।
type State = 'CLOSED' | 'OPEN' | 'HALF_OPEN';
class MiniBreaker {
private state: State = 'CLOSED';
private failures = 0;
private openedAt = 0;
constructor(private threshold = 3, private resetMs = 1000) {}
async call<T>(fn: () => Promise<T>): Promise<T> {
if (this.state === 'OPEN') {
if (Date.now() - this.openedAt >= this.resetMs) this.state = 'HALF_OPEN';
else throw new Error('Circuit OPEN: failing fast');
}
try {
const result = await fn();
this.failures = 0;
this.state = 'CLOSED';
return result;
} catch (e) {
this.failures++;
if (this.failures >= this.threshold) {
this.state = 'OPEN';
this.openedAt = Date.now();
}
throw e;
}
}
get current() { return this.state; }
}
async function main() {
const breaker = new MiniBreaker(2, 500);
const flaky = () => Promise.reject(new Error('downstream down'));
for (let i = 0; i < 4; i++) {
try { await breaker.call(flaky); }
catch (e) { console.log(`call ${i}: ${(e as Error).message} [state=${breaker.current}]`); }
}
}
main();opossum का उपयोग
अपने हाथ से बनाए गए breaker कठिन हिस्सों को छोड़ देते हैं: रोलिंग-विंडो आँकड़े, प्रतिशत-आधारित सीमाएँ, half-open परीक्षण सीमाएँ और मेट्रिक्स। opossum प्रचलित Node.js circuit breaker है और NestJS प्रदाताओं के साथ आसानी से एकीकृत हो जाता है।
timeout— कॉल को विफल मानने से पहले की अवधि।errorThresholdPercentage— विंडो में विफलताओं का वह प्रतिशत जिस पर breaker सक्रिय हो जाता है।resetTimeout— HALF_OPEN परीक्षण से पहले OPEN रहने की अवधि।rollingCountTimeout— सांख्यिकीय विंडो का आकार।
इसे npm i opossum और npm i -D @types/opossum से इंस्टॉल करें।
import CircuitBreaker from 'opossum';
const options: CircuitBreaker.Options = {
timeout: 3000, // a call slower than 3s counts as a failure
errorThresholdPercentage: 50, // trip when >=50% of calls fail
resetTimeout: 10000, // stay OPEN for 10s, then try HALF_OPEN
rollingCountTimeout: 10000, // 10s statistical window
rollingCountBuckets: 10, // split the window into 10 buckets
};
// The action is the function we want to protect
async function fetchUser(id: string): Promise<{ id: string }> {
// ... real HTTP call to a downstream user service ...
return { id };
}
export const userBreaker = new CircuitBreaker(fetchUser, options);NestJS Provider में डाउनस्ट्रीम कॉल को लपेटना
NestJS में breaker ऐसे provider में होना चाहिए जो एक तार्किक निर्भरता का स्वामी हो। CircuitBreaker को constructor (या factory) में एक बार बनाएँ, ताकि रोलिंग आँकड़े अनुरोधों के बीच बने रहें — प्रति अनुरोध कभी नया breaker न बनाएँ, वरना वह निर्भरता की सेहत को कभी समझ नहीं पाएगा।
एक ऐसी method उपलब्ध कराएँ जो breaker.fire(...) को delegate करे।
import { Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { firstValueFrom } from 'rxjs';
import CircuitBreaker from 'opossum';
interface PricingDto { sku: string; cents: number; }
@Injectable()
export class PricingClient {
private readonly breaker: CircuitBreaker<[string], PricingDto>;
constructor(private readonly http: HttpService) {
this.breaker = new CircuitBreaker(
(sku: string) => this.requestPrice(sku),
{ timeout: 2000, errorThresholdPercentage: 50, resetTimeout: 15000 },
);
}
private async requestPrice(sku: string): Promise<PricingDto> {
const res = await firstValueFrom(
this.http.get<PricingDto>(`https://pricing.internal/skus/${sku}`),
);
return res.data;
}
getPrice(sku: string): Promise<PricingDto> {
return this.breaker.fire(sku);
}
}Fallback: शालीनता से क्षमता घटाना
तुरंत विफल होना अच्छा है, लेकिन उपयोगकर्ता को कठोर error लौटाना अक्सर कुछ उचित लौटाने से बदतर होता है। opossum का fallback() तब चलता है जब action reject हो या breaker OPEN हो।
- कैश की गई या पिछली ज्ञात-सही value परोसें।
- सुरक्षित डिफ़ॉल्ट लौटाएँ (उदाहरण के लिए, recommendations की खाली सूची)।
- काम को छोड़ने के बजाय बाद के लिए कतार में रखें।
fallback को वही arguments और उसे सक्रिय करने वाला error मिलता है, इसलिए आप उसके आधार पर अलग शाखा चुन सकते हैं।
import CircuitBreaker from 'opossum';
type Recommendation = { id: string };
function buildRecommendationBreaker(
action: (userId: string) => Promise<Recommendation[]>,
) {
const breaker = new CircuitBreaker(action, {
timeout: 1500,
errorThresholdPercentage: 40,
resetTimeout: 20000,
});
// When OPEN or the action fails, return a safe empty list
breaker.fallback((_userId: string, err?: Error) => {
if (err) console.warn('recommendations degraded:', err.message);
return [] as Recommendation[];
});
return breaker;
}Breaker Events पर नज़र रखना
जो breaker चुपचाप अवस्था बदलता है, वह संचालन संबंधी एक अंधा क्षेत्र बन जाता है। opossum हर महत्वपूर्ण बदलाव के लिए events जारी करता है। इन्हें अपने logger और मेट्रिक्स से जोड़ें, ताकि ऑन-कॉल इंजीनियर वास्तविक समय में पूरी स्थिति देख सकें।
open/halfOpen/close— अवस्था में बदलाव।reject— breaker OPEN होने के कारण अस्वीकार की गई कॉल।timeout— कॉन्फ़िगर किए गए timeout से अधिक समय लेने वाली कॉल।fallback— fallback का उपयोग किया गया।success/failure— fire की गई प्रत्येक कॉल का परिणाम।
import { Logger } from '@nestjs/common';
import CircuitBreaker from 'opossum';
export function attachBreakerTelemetry(
breaker: CircuitBreaker,
name: string,
logger = new Logger('CircuitBreaker'),
) {
breaker.on('open', () => logger.error(`[${name}] OPEN - failing fast`));
breaker.on('halfOpen', () => logger.warn(`[${name}] HALF_OPEN - probing`));
breaker.on('close', () => logger.log(`[${name}] CLOSED - recovered`));
breaker.on('reject', () => logger.warn(`[${name}] call rejected (OPEN)`));
breaker.on('timeout', () => logger.warn(`[${name}] call timed out`));
breaker.on('fallback', () => logger.warn(`[${name}] fallback served`));
}Timeout, breaker का हिस्सा है
एक आम गलती यह है कि breaker का timeout अंतर्निहित HTTP client timeout से अधिक रखा जाता है। यदि आपका axios timeout 30s है, लेकिन breaker timeout 3s है, तो opossum 3s पर हार मान लेता है — यह अच्छा है — लेकिन socket डाउनस्ट्रीम में अब भी खुला रह सकता है।
दोनों को समायोजित करें: breaker timeout को transport timeout से थोड़ा कम रखें और सुनिश्चित करें कि transport वास्तव में कॉल को abort करता है। पूरा उद्देश्य यह सीमित करना है कि कोई एक कॉल किसी संसाधन को कितनी देर तक रोके रख सकती है।
import { Module } from '@nestjs/common';
import { HttpModule } from '@nestjs/axios';
@Module({
imports: [
HttpModule.register({
timeout: 2500, // axios aborts the socket at 2.5s
maxRedirects: 0,
}),
],
})
export class DownstreamModule {}
// Breaker timeout (e.g. 2000ms) should sit just BELOW the axios timeout
// so opossum records the failure while the socket is still being released.प्रति ऐप नहीं, प्रत्येक निर्भरता के लिए एक breaker
बल्कहेडिंग का अर्थ है विफलताओं को अलग रखना, ताकि बीमार निर्भरता स्वस्थ निर्भरता को डुबो न सके। प्रत्येक डाउनस्ट्रीम के लिए अपनी breaker instance दें और उसकी SLA के अनुसार सीमाएँ निर्धारित करें।
- कोई अस्थिर analytics सेवा payments को प्रभावित किए बिना सक्रिय हो सकती है।
- विलंबता-संवेदी auth कॉल के लिए कड़ा timeout रखें; batch report कॉल के लिए ढीला timeout रखा जा सकता है।
- प्रति-निर्भरता मेट्रिक्स डैशबोर्ड को पढ़ने योग्य बनाते हैं।
असंबंधित कॉल के लिए एक ही वैश्विक breaker साझा न करें — उनके आँकड़े एक-दूसरे को दूषित कर देंगे।
import { Injectable } from '@nestjs/common';
import CircuitBreaker from 'opossum';
@Injectable()
export class BreakerRegistry {
private readonly breakers = new Map<string, CircuitBreaker>();
get<TArgs extends unknown[], TRet>(
name: string,
action: (...args: TArgs) => Promise<TRet>,
options: CircuitBreaker.Options,
): CircuitBreaker<TArgs, TRet> {
const existing = this.breakers.get(name);
if (existing) return existing as CircuitBreaker<TArgs, TRet>;
const breaker = new CircuitBreaker(action, options);
this.breakers.set(name, breaker);
return breaker;
}
}Probes के लिए Breaker Health उपलब्ध कराना
संचालन की दृष्टि से आप चाहते हैं कि breaker की अवस्था health endpoint में दिखाई दे और Prometheus द्वारा scrape की जा सके। opossum breaker.stats (success, failure, timeout और reject की गिनतियाँ) तथा breaker.opened / breaker.halfOpen बूलियन उपलब्ध कराता है।
एक कस्टम Terminus health indicator OPEN breakers को degraded — आवश्यक रूप से down नहीं — स्थिति के रूप में रिपोर्ट कर सकता है, ताकि orchestrator अनावश्यक रूप से ऐसे pod को समाप्त न करें जो सही ढंग से लोड कम कर रहा है।
import { Injectable } from '@nestjs/common';
import { HealthIndicator, HealthIndicatorResult } from '@nestjs/terminus';
import CircuitBreaker from 'opossum';
@Injectable()
export class BreakerHealthIndicator extends HealthIndicator {
check(name: string, breaker: CircuitBreaker): HealthIndicatorResult {
const isUp = !breaker.opened;
return this.getStatus(name, isUp, {
state: breaker.opened ? 'open' : breaker.halfOpen ? 'half_open' : 'closed',
failures: breaker.stats.failures,
timeouts: breaker.stats.timeouts,
rejects: breaker.stats.rejects,
});
}
}सीमाओं को समझदारी से समायोजित करना
खराब सीमाएँ किसी breaker के न होने से भी बदतर होती हैं। वास्तविक ट्रैफ़िक के आधार पर इन्हें समायोजित करें:
- errorThresholdPercentage बहुत कम (जैसे 10%) होने पर सामान्य jitter में भी breaker सक्रिय हो जाता है; बहुत अधिक (जैसे 90%) होने पर इसका उद्देश्य ही विफल हो जाता है। 40-60% एक सामान्य शुरुआती सीमा है।
- resetTimeout बहुत कम होने पर उबरती हुई सेवा पर लगातार दबाव पड़ता है; बहुत अधिक होने पर recovery में देरी होती है। शुरुआत 10-30s के आसपास करें।
- कम ट्रैफ़िक का ध्यान रखें: विंडो में केवल 2 कॉल हों, तो एक विफलता 50% होती है। opossum का
volumeThresholdप्रतिशत के आधार पर breaker सक्रिय होने से पहले कॉल की न्यूनतम संख्या आवश्यक बनाता है।
import CircuitBreaker from 'opossum';
const options: CircuitBreaker.Options = {
timeout: 2000,
errorThresholdPercentage: 50,
resetTimeout: 15000,
rollingCountTimeout: 10000,
rollingCountBuckets: 10,
volumeThreshold: 10, // need >=10 calls in the window before % can trip
// errorFilter lets you NOT count expected errors (e.g. 404) as failures:
errorFilter: (err: { statusCode?: number }) => err?.statusCode === 404,
};
export { options };त्वरित जाँच: सही व्यवहार चुनना
लोड के दौरान circuit breaker कैसे व्यवहार करता है, इसकी अपनी समझ जाँचें।
पुनरावलोकन
अब आप जानते हैं कि डाउनस्ट्रीम विफलता को अपनी NestJS सेवा को बंद करने से कैसे रोका जाए:
- पैटर्न: breaker CLOSED, OPEN और HALF_OPEN के बीच बदलता है; OPEN का अर्थ है timeout की प्रतीक्षा करने के बजाय तुरंत विफल होना।
- opossum:
timeout,errorThresholdPercentage,resetTimeoutऔरvolumeThresholdकॉन्फ़िगर करें, फिर कॉल कोnew CircuitBreaker(action, options)से लपेटें औरbreaker.fire()चलाएँ। - एक बार बनाएँ: breaker को provider/registry में बनाएँ, ताकि रोलिंग आँकड़े बने रहें — बल्कहेडिंग के लिए प्रत्येक निर्भरता का एक breaker रखें।
- क्षमता घटाएँ: कैश की गई या सुरक्षित-डिफ़ॉल्ट प्रतिक्रियाओं के लिए
fallback()register करें। - निगरानी करें:
open/close/reject/timeoutevents को logs और मेट्रिक्स से जोड़ें और health probe में अवस्था दिखाएँ।
backoff वाले पुनःप्रयास और timeouts के साथ मिलकर circuit breakers resilient, SLO-अनुकूल वितरित प्रणालियों की आधारशिला हैं।
एआई शिक्षक के साथ TypeScript सीखें — निःशुल्क
अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।
- पाठ्यक्रम
- 20
- पाठ
- 76
अक्सर पूछे जाने वाले प्रश्न
क्या “डाउनस्ट्रीम विफलताओं के लिए सर्किट ब्रेकर” पाठ निःशुल्क है?
हाँ—“डाउनस्ट्रीम विफलताओं के लिए सर्किट ब्रेकर” का पूरा पाठ यहाँ वेब पर निःशुल्क पढ़ा जा सकता है। इंटरैक्टिव अभ्यास (अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर) करने और NestJS एंटरप्राइज़ बैकएंड API पाठ्यक्रम का बाकी हिस्सा अनलॉक करने के लिए CoddyKit PRO लें। NestJS एंटरप्राइज़ बैकएंड API पाठ्यक्रम में कुल 4 पाठ शामिल हैं।
“डाउनस्ट्रीम विफलताओं के लिए सर्किट ब्रेकर” में मैं क्या सीखूँगा?
opossum-शैली के सर्किट ब्रेकर एकीकरण से सेवाओं को क्रमिक विफलताओं से सुरक्षित रखिए। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ NestJS एंटरप्राइज़ बैकएंड API का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।
क्या NestJS एंटरप्राइज़ बैकएंड API शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?
पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर NestJS एंटरप्राइज़ बैकएंड API शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 2वाँ पाठ है।
“डाउनस्ट्रीम विफलताओं के लिए सर्किट ब्रेकर” पाठ पूरा करने में कितना समय लगता है?
CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।
क्या मैं इस NestJS एंटरप्राइज़ बैकएंड API पाठ में कोड लिख और चला सकता हूँ?
हाँ। हर NestJS एंटरप्राइज़ बैकएंड API पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।
इस पाठ्यक्रम के सभी पाठ
- इंटरसेप्टर के साथ समय-सीमा, पुनःप्रयास और बल्कहेड
- डाउनस्ट्रीम विफलताओं के लिए सर्किट ब्रेकर
- OpenTelemetry के साथ वितरित ट्रेसिंग
- SLO और त्रुटि बजट निर्धारित करना