GH GambleHub

Circuit Breaker და retrai

Circuit Breaker და retrai

1) რატომ არის ეს აუცილებელი?

ქსელები არასაიმედოა: ლატენტობა პულსირდება, კვანძები ეცემა, ლიმიტები მიიღწევა. Retrais იხსნის მოკლევადიანი წარუმატებლობებისგან, ხოლო Circuit Breaker იცავს სისტემას კასკადის უკმარისობისგან და „Same-DDoS“. კომბინაცია სწორ ტაიმაუტებთან და ლიმიტებთან ერთად ინარჩუნებს SLO- ს, სტაბილიზაციას უწევს კუდის შეფერხებებს და „გოგონების“ ფასს.

2) ძირითადი პრინციპები

ჯერ ტაიმაუტები, შემდეგ retrai, შემდეგ Circuit Breaker.
ჩვენ მხოლოდ idempotent ოპერაციებს ვატარებთ (GET, უსაფრთხო POST/PUT idempotent გასაღებით).
გამოყავით რეაგირების ბიუჯეტი: საწყისი RPS- ის 10-15% -იანი მარშრუტით.
ლოკალიზებული უკმარისობა: bulkhead (ცალკეული აუზები/კვოტები) + rate-limit.
დეგრადაციის დროს - სწრაფი უკმარისობა, graceful-degradation/stumbs.

3) რეტრაევის სემანტიკა

როდესაც ტირილი

Timeouts შეცდომები: Timeouts, 5xx, ქსელის მიუწვდომლობა, 429 ('Retry-After- ის შემდეგ').
თქვენ არ შეგიძლიათ გადახვიდეთ: აშკარა ბიზნეს შეცდომები (4xx-429), side-effects იდემპოტენტურობის გარეშე (გადახდა გასაღების გარეშე).

სტრატეგიები

Exponential backoff + jitter (სრული ან ერთგვაროვანი): ამცირებს რეაგირების პაკეტებს.
Max attempts: 1-2 (იშვიათად 3) - უფრო საზიანოა.
Budget: გლობალური რეაგირების მრიცხველი/წმ მომსახურებისთვის და per-request „retry tokens“.
Hedging (იშვიათად): მოთხოვნის პარალელური დუბლი t-quantil- ის შემდეგ (p95) - მხოლოდ მკაცრად იდემპოტენტური კითხვებისთვის.

ფსევდო კოდი backoff + ჯიტერი:
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 <upstream timeout: იმისათვის, რომ არ დაზოგოთ „ზომბების“ მოთხოვნები.
Делите: connect timeout, read timeout, overall deadline.
Tail-aware Timauts: ჩვენ გავაფართოვებთ p95/p99 + მცირე რეზერვს.
გამოიყენეთ ზოგადი ვადაგადაცილებული ველი (მაგალითად, gRPC 'deadline') და გაატარეთ იგი ჯაჭვში.

5) Circuit Breaker: როგორ მუშაობს

სახელმწიფოები:
  • Closed: გადის ტრაფიკს, მიიჩნევს შეცდომებს/ლატენტობას.
  • ღია: დაუყოვნებლივ აძლევს სწრაფ უარს (ან სარეზერვო პასუხს).
  • Half-Open: შემოწმების მოთხოვნები; წარმატების შემთხვევაში - დახურულია.
გახსნის ბარიერი:
  • შეცდომები/ტაიმაუტები აღემატება X% -იან წილს N მოთხოვნის/წამის ფანჯრის ან p99 ბარიერის ზემოთ.
  • შესაბამისი მოცურების სტატისტიკა და მინიმალური მოცულობა (მაგალითად, 50 მოთხოვნა).

6) Bulkhead, კვოტები და „გაყოფა და დაპყრობა“

ნაერთების ცალკეული ტყვიები per-upstream და per-fich.
კვოტები ფრენის მოთხოვნით; ზედმეტი - სწრაფი უარი.
დეფიციტის შემთხვევაში - დაბალი პრიორიტეტის მქონე შეცდომების დეგრადაცია (feature flags).

7) პერიმეტრის ინტეგრაცია (Envoy/Istio/Nginx)

Envoy (retry + outlier + 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 (VirtualService fault/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) ბიბლიოთეკები და კოდი (snippet დასტის)

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: თითოეული retry ხარჯავს ნიშანს; აუზი შეზღუდულია.
დაუკავშირდით error-budget- ს: ბარიერის ზემოთ მდებარე ბარში - გამორთეთ ჭრილობა, უფრო ხშირად გახსენით CB, ჩართეთ დეგრადაცია.
კანარის გამოშვებები: კანარებზე შეამცირეთ მცდელობები და ნიშნები.

10) ჰედინგი (ფრთხილად)

დაიწყეთ დამატებითი მოთხოვნა p95 ვადის გასვლის შემდეგ, გააუქმეთ წაგება.
მხოლოდ კითხვისა და „უსაფრთხო“ იდემპოტენტური ოპერაციებისთვის; შეზღუდეთ წილი (1-5%).
დააკვირდით opstrim- ზე დატვირთვის ზრდას.

11) დაკვირვება

RED მეტრიკები მარშრუტებზე: Rate, Error, Duration (p50/p95/p99).
CB მეტრიკა: სახელმწიფო (Open/half-Open), გახსნის სიხშირე, გამოტოვებული/უარის თქმის მოთხოვნები.
Retrai: attempts/request, retry-rate, დამწვარი ნიშნები.
პერიმეტრი: outlier-ejection, ejection-rate.
ტრეისი: გამოიყენეთ 'retry _ attempt', 'cb _ state', 'hedged = true', შეეცადეთ 'trace _ id'.

12) ინტეგრაცია არქიტექტურასთან

Bulkhead + CB თითოეული კრიტიკული აფსიდისთვის.
რიგები/ასინქრონი: გრძელი ოპერაციებისთვის, გიჟური ტაიმაუტის ნაცვლად.
Kash/stumbs: fail-Open- ის არა კრიტიკული დარტყმებისთვის.
Autoskale: ის არ ანაზღაურებს ცუდ ჭიდაობას - ჯერ შეაჩერეთ „ქარიშხალი“.

13) ანტი შაბლონები

Retrai გარეშე Taimauts - „დაკიდებული“ კონექტორები და ტყვიების ამოწურვა.
Indempotent ოპერაციების განმეორება (ორმაგი ჩამოწერა).
გაუთავებელი ექსპონენციალური ზრდა cap და jitter გარეშე.
ყველა სტრიქონზე ერთი CB არის წარუმატებლობის გადატანა მთელ პროდუქტზე.
უგულებელყოფა 429/' Retry-After '.
კლიენტის ტაიმუტი უფრო გრძელია, ვიდრე აფსიდი (ან საერთოდ არა).
„მკურნალობა“ ბიზნესის შეცდომებით.

14) განხორციელების სიის სია (0-30 დღე)

0-7 დღე

დაადგინეთ მარშრუტები და მათი idempotence.
დაუსვით ტაიმაუტები (კავშირი/read/overall), ჩართეთ მინიმალური ჭრილობები (× 1) და CB ნაგულისხმევი.
გამოყავით აუზები/კვოტები ძირითადი აფსიდებისთვის.

8-20 დღე

ჩართეთ ჯიტერი და გლობალური რეაგირების ბიუჯეტი, რეტრო ალერტები.
პერიმეტრზე outlier-ejection პარამეტრი, დაბალი ფასის სწრაფი უკმარისობა.
დაშბორდები RED + CB/Retry, ეტიკეტები.

21-30 დღე

ჭიდაობის კანარის პროფილები (ნაკლები მცდელობები), თამაშის დღე „ნელი/ნელი აფთიაქი“.
პოლიტიკის დოკუმენტირება: ვინ/რა ახდენს რეაგირებას, შეზღუდვებს, გამონაკლისებს.
გადახედეთ p95/p99 და ტაიმაუტები მონაცემების მიხედვით, და არა თვალებით.

15) სიმწიფის მეტრიკა

მარშრუტების 100% -ს აქვს ტაიმაუტები და Retrais/SV დოკუმენტირებული პოლიტიკა.
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) დასკვნა

სტაბილურობა არის დისციპლინა: Taimauts-retrai (ჯიტერი და ბიუჯეტი), Circuit Breaker + bulkhead/კვოტები და სწრაფი უარი. პერიმეტრის პარამეტრები (outlier-ejection), ჩამოკიდეთ dashbords RED/CB/Retry, დააფიქსირეთ idempotenty პოლიტიკა და არ დაივიწყოთ ბიზნეს SLI. შემდეგ მოკლე ჩავარდნები დარჩება შეუმჩნეველი და ნამდვილი ინციდენტები არ გადაიქცევა კასკადის ვარდნად.

Contact

დაგვიკავშირდით

დაგვიკავშირდით ნებისმიერი კითხვის ან მხარდაჭერისთვის.ჩვენ ყოველთვის მზად ვართ დაგეხმაროთ!

Telegram
@Gamble_GC
ინტეგრაციის დაწყება

Email — სავალდებულოა. Telegram ან WhatsApp — სურვილისამებრ.

თქვენი სახელი არასავალდებულო
Email არასავალდებულო
თემა არასავალდებულო
შეტყობინება არასავალდებულო
Telegram არასავალდებულო
@
თუ მიუთითებთ Telegram-ს — ვუპასუხებთ იქაც, დამატებით Email-ზე.
WhatsApp არასავალდებულო
ფორმატი: ქვეყნის კოდი და ნომერი (მაგალითად, +995XXXXXXXXX).

ღილაკზე დაჭერით თქვენ ეთანხმებით თქვენი მონაცემების დამუშავებას.