Circuit Breaker և reaker
Circuit Breaker և reaker
1) Ինչո՞ ւ է դա անհրաժեշտ
Ցանցերը անվստահելի են 'լատենտային իմպուլսացիա, նվազում են, սահմանները հասնում են։ Retrai-ը փրկվում է կարճ ձախողումներից, իսկ Circuit Breaker-ը պաշտպանում է համակարգը կասկադային ձախողումներից և «DDoS» -ից։ Ճիշտ թայմաուտների և լիմիտների հետ համադրությունը պահպանում է SLO, կայունացնում է պոչի ուշացումները և «աղջիկների» գինը։
2) Հիմնական սկզբունքները
Սկզբում թայմաուտները, հետո retrai, ապա Circuit Breaker-ը։
Retraim միայն idempotent վիրահատություններ (GET, ապահով POST/PUT 'idempotent բանալին)։
Հատկացրեք գետերի բյուջեին ՝ 10-15 տոկոսը RPS-ի երթուղու վրա։
Անջատեք մերժումը 'bulkhead (առանձին փամփուշտներ/քվոտաներ) + rate-limit։
Քայքայման դեպքում արագ հրաժարվելը (fail-fox), graceful-degradation/degradation։
3) Գետերի իմաստաբանությունը
Երբ կտրել
Տրանսիզենտ սխալները ՝ timeouts, 5xx, ցանցային անհասանելիությունը, 429 («Retry-After» -ից հետո)։
Դուք չեք կարող ասել, որ ակնհայտ բիզնես սխալները (4xx 35429), side effects-ը առանց idempotents-ի (առանց ստեղների)։
Ռազմավարություն
Exponential backoff + jitter (ամբողջական կամ միատեսակ), բացակայում է ռետրերի հոտերը։
Max attemp.ru: 1-2 (հազվադեպ 3) - ավելի շատ վնասակար։
Budget: գլոբալ ռելսերի հաշվիչ/վրկ ծառայության վրա և per-request «retry tokens»։
Hedging (հազվադեպ) 't-quanali (p95) - միայն խիստ idempotent ընթերցումների համար։
Կեղծ backoff + jitter
python base = 100 # ms for attempt in range(1, max_attempts+1):
try:
return call()
except Transient as e:
if attempt == max_attempts: raise sleep_ms = min(cap_ms, base 2(attempt-1))
sleep(random(0, sleep_ms)) # full jitter
4) Թայմաուտները և «արագ մերժումը»
Client timeout
Делите: connect timeout, read timeout, overall deadline.
Tail-ault timauts: Մենք ապրում ենք p95/p99 + փոքր պահուստում։
Օգտագործեք ընդհանուր dedline դաշտը (օրինակ gRPC 'deadium ") և այն նետեք շղթայի վրայով։
5) Circuit Breaker: Ինչպես է աշխատում
Վիճակը
Closed 'բաց է թողնում, կարծում է սխալներ/լատենտ։
Բաց 'անմիջապես տալիս է արագ հրաժարումը (կամ պահեստային պատասխանը)։
Half-Open: փորձարկման հարցումներ; հաջողության դեպքում փակվում է։
Բացահայտման շեմն է
Սխալները/թայմաուտները գերազանցում են X տոկոսը N-ի պատուհանի/վայրկյան կամ p99-ից բարձր շեմից։
Relevantna-ը սայթաքող վիճակագրությունն է և նվազագույն ծավալը (օրինակ ՝ 3,50 հարցումներ)։
6) Bulkhead, քվոտաներ և «բաժանիր և իշխիր»
Per-upstream և per-fich առանձին գնդակներ։
Քվոտաները in-flight հարցումների վրա։ ավելին 'արագ մերժումը։
Պակասի դեպքում ֆիչի քայքայումը ցածր գերակայությամբ (feature flags)։
7) Ինտեգրումը պարագծի հետ (Envoy/Istio/Nginx)
Envoy (retry + medier + CB, գաղափարը)
yaml routes:
- match: { prefix: "/api" }
route:
cluster: upstream_api timeout: 2s retry_policy:
retry_on: "connect-failure,reset,retriable-4xx,5xx"
num_retries: 2 per_try_timeout: 600ms retry_back_off: { base_interval: 100ms, max_interval: 800ms }
hedge_policy:
hedge_on_per_try_timeout: true initial_requests: 1 additional_request_chance: { numerator: 5, denominator: HUNDRED } # 5%
clusters:
- name: upstream_api circuit_breakers:
thresholds:
- priority: DEFAULT max_connections: 500 max_requests: 1000 max_retries: 200 outlier_detection:
consecutive_5xx: 5 interval: 5s base_ejection_time: 30s max_ejection_percent: 50
Istio (Virtum Syfox/retry, սեղմված օրինակ)
yaml apiVersion: networking. istio. io/v1beta1 kind: VirtualService spec:
hosts: ["payments"]
http:
- route: [{ destination: { host: payments } }]
timeout: 2s retries:
attempts: 2 perTryTimeout: 600ms retryOn: "5xx,connect-failure,refused-stream,reset"
Nginx Ingress (ծանոթություններ)
yaml nginx. ingress. kubernetes. io/proxy-connect-timeout: "2"
nginx. ingress. kubernetes. io/proxy-read-timeout: "2"
nginx. ingress. kubernetes. io/proxy-next-upstream: "error timeout http_502 http_503 http_504"
nginx. ingress. kubernetes. io/proxy-next-upstream-tries: "2"
8) Գրադարաններ և կոդը (stek-sinpets)
Java (Resilience4j):java var cb = CircuitBreaker. ofDefaults("psp");
var retry = Retry. of("psp-retry",
RetryConfig. custom()
.maxAttempts(2)
.waitDuration(Duration. ofMillis(200))
.intervalFunction(IntervalFunction. ofExponentialRandomBackoff(100, 2. 0, 0. 5) )//jitter
.retryExceptions(SocketTimeoutException. class, IOException. class)
.build());
Supplier<Response> decorated =
CircuitBreaker. decorateSupplier(cb,
Retry. decorateSupplier(retry, () -> client. call()));
return Try. ofSupplier(decorated)
.recover(BusinessException. class, fallback())
.get();
Go (context deadline + backoff):
go ctx, cancel:= context. WithTimeout(context. Background(), 2time. Second)
defer cancel()
var lastErr error for i:= 0; i < 2; i++ {
reqCtx, stop:= context. WithTimeout(ctx, 600time. Millisecond)
lastErr = call(reqCtx)
stop()
if lastErr == nil { break }
sleep:= time. Duration(rand. Intn(1<<uint(7+i))) time. Millisecond // full jitter time. Sleep(min(sleep, 800time. Millisecond))
}
if lastErr!= nil { return fastFail() }
Node. js (got + p-retry):
js import pRetry from 'p-retry';
await pRetry(() => got(url, { timeout: { connect: 500, request: 2000 } }), {
retries: 2,
factor: 2,
randomize: true,
minTimeout: 100,
maxTimeout: 800,
onFailedAttempt: e => { if (isBusiness(e)) throw e; }
});
9) Գետերի և SLO բյուջեն
Մուտքագրեք retry tokens: Յուրաքանչյուր ռետրա ծախսում է հոսանքը։ պուլիմիտացված է։
Համատեղեք error-budget-ի հետ 'շեմից վերևում գտնվող burn-rate-ով, մենք անջատում ենք գետերը, բացում CB-ն ավելի հաճախ, ներառյալ դեգրադացիան։
Կանարեխի ածխաջրածինները 'քարերի վրա նվազեցրեք փորձերը և հոսանքները։
10) Hedging (զգույշ)
Սկսեք լրացուցիչ հարցումը p95-dedline-ից հետո 'վերացնելով պարտվողին։
Միայն կարդալու և «անվտանգ» idempotent վիրահատությունների համար։ սահմանափակեք մասնաբաժինը (1-5%)։
Հետևեք բեռնափոխադրումների աճին։
11) Դիտողականությունը
RED մետրիկները երթուղիներով ՝ Rate, Error, Duration (p50/p95/p99)։
CB-մետրիկները ՝ վիճակը (բաց/half-open), բացահայտումների հաճախականությունը, բաց թողված/մերժված հարցումները։
Retrai: attemp.ru/request, retry-rate, այրված հոսանքներ։
Պարիմետրը ՝ wwww.ier-ej.ru, ejw.ru-rate։
Թրեյզներ 'antretry _ attempt', «cb _ state», «hedged = mede», բացեք «trace _ id»։
12) Ինտեգրումը ճարտարապետության հետ
Bulkhead + CB-ը յուրաքանչյուր կրիտիկական ապստրիմի համար։
Հերթեր/ասինհրոն 'երկար վիրահատությունների համար խենթ թայմաուտների փոխարեն։
Քեշ/կոճակները 'ոչ կրիտիկական ֆիգուրի համար fail-Open-ում։
Autockayle: չի փոխհատուցում վատ ռետրերը, նախ կանգնեցրեք «փոթորիկը»։
13) Anti-patterna
Retrai առանց թայմաուտների «կախված» և փամփուշտների սպառումը։
Ոչ գաղափարական վիրահատությունների խոհարար (կրկնակի ապամոնտաժումներ)։
Անսահման էքսպոնենցիալ աճը առանց cap և ջիթերի։
Միակ CB-ը բոլոր apstrimes-ի վրա բացատրվում է ամբողջ ապրանքի հրաժարումը։
Անտեսում 429/« Retry-After »։
Հաճախորդի թայմաուտը ավելի երկար է, քան ապստրիման (կամ ընդհանրապես ոչ)։
«Բուժել» բիզնես սխալները ելույթներով։
14) Իրականացման չեկի ցուցակը (0-30 օր)
0-7 օր
Ռուսական երթուղիները և նրանց կուռքերը։
Թույլ տվեք թայմաուտները (connational/read/overall), միացրեք նվազագույն ռետրան (651) և CB լռելյայն։
Բաժանեք փամփուշտները/քվոտաները (bulkhead) հիմնական ապստրիմների համար։
8-20 օր
Միացրեք ջիտտերը և գլոբալ ռեգերի բյուջեն, ալտերտերը retry-rate-ով։
Պարագծի վրա պարագծի պարամետրերը, արագ հրաժարվելը low-prio ֆիչի համար։
Dashbords RED + CB/Retry, նետերով։
21-30 օր
Գետերի կանարյան պրոֆիլները (ավելի քիչ փորձեր), game-day «դանդաղ/ֆայլ»։
Փաստարկեք քաղաքականությունը 'ով/ինչ է կտրում, սահմաններ, բացառություններ։
Վերանայեք p95/p99 և թայմաուտները տվյալների համաձայն, ոչ թե աչքին։
15) Հասունության մետրերը
Երթուղիների 100 տոկոսը ունեն թայմաուտներ և հաշվարկված ռետրերի քաղաքականություն/ԹԱՍ։
Retry-rate-ը տեղադրվում է բյուջեում (10-15 տոկոս), միջադեպերի ժամանակ ոչ մի աճ չկա։
CB-ն աշխատում է ավելի շուտ, քան ամբողջ փամփուշտը։ կասկադային մերժումներ չկան։
Թրեյսները ցույց են տալիս փորձեր/hedging; p99 պոլիմիլեն պիկի ժամանակ։
Կանարեկային ալգորիթմները օգտագործում են գետերի «խնամքի» պրոֆիլը։
16) Միգրացիայի կարճ օրինակներ
Resilience4j YAML (Spring Boot, идея):yaml resilience4j:
circuitbreaker:
instances:
psp:
slidingWindowType: COUNT_BASED slidingWindowSize: 100 minimumNumberOfCalls: 50 failureRateThreshold: 50 waitDurationInOpenState: 30s permittedNumberOfCallsInHalfOpenState: 5 retry:
instances:
psp:
maxAttempts: 2 waitDuration: 200ms enableExponentialBackoff: true exponentialBackoffMultiplier: 2. 0 retryExceptions:
- java. net. SocketTimeoutException
- java. io. IOException
Envoy rate-limit (գաղափարի մի հատված)
yaml rate_limits:
- actions:
- generic_key: { descriptor_value: "api. payments" }
17) Եզրակացություն
Կայունությունը կարգապահությունն է 'timautes retrai (ջիթերի և բյուջեի հետ) www.Circuit Breaker + bulkhead/քվոտայի և արագ հրաժարվելու համար։ Պարագծի պարամետրերը (wwww.ier-ej.ru), կախեք RED/CB/Retry dashbords, տեղադրեք idempotenty քաղաքականությունը և մի մոռացեք բիզնես SLI-ի մասին։ Այդ ժամանակ կարճ ձախողումները կմնան աննկատ, իսկ իրական միջադեպերը չեն վերածվի կասկադային անկման։