Timeout და circuit control
1) რატომ არის ეს აუცილებელი?
სისტემები ეცემა არა ერთი „საბედისწერო“ წარუმატებლობისგან, არამედ შეფერხებების დაგროვებისა და „ტალღური“ რეაგირებისგან. Taimauts ზღუდავს ლოდინის დროს და ათავისუფლებს რესურსებს, ხოლო circuit კონტროლი (breaker + shedding + ადაპტირებული კონკურენცია) არ იძლევა დეგრადაციას დამოკიდებულების ჯაჭვის გასწვრივ. მიზანია p95/p99 შენარჩუნება სამიზნე საზღვრებში და შეინარჩუნოს წვდომა ნაწილობრივი უარი.
2) ძირითადი განმარტებები
2. 1 ტაიმუთის სახეობები (L7/L4)
Connect Timeout არის TCP/TLS კავშირის დამყარება.
TLS/Handshake timeout - TLS/HTTP2 პრეფიქსი.
Write timeout - მოთხოვნის გაგზავნა (სხეულის ჩათვლით).
Read Timeout - პასუხის ან/და მთელი სხეულის პირველი ბაიტის მოლოდინი.
Idle/Keep-Alive Timeout არის არააქტიური ნაერთი.
Overall deadline არის „რთული“ ვადა მთელი თხოვნისთვის (end-to-end).
2. 2 ტაიმუტის ბიუჯეტი (deadline budget)
ჩვენ განვასხვავებთ სამიზნე 'deadline_total "და იყოფა ეტაპზე:- `ingress (gateway) + authZ + app + DB/cache + outbound PSP`.
- კარიბჭე: 30 ms,
- დანართი: 120 ms,
- BD: 120 ms,
- PSP: 100 ms,
- რეზერვი: 30 ms.
2. 3 გაუქმება და გაუქმება
'deadline'/'timeout' უნდა გადაეცეს ჯაჭვს (კონტექსტი, სათაურები, gRPC Deadline). ამის შემდეგ - ფონის ოპერაციების გაუქმება (abort/ctx cancel), ბლოკირების/სემფორების გაწმენდა.
3) ტაიმაუტის დაყენების სტრატეგიები
1. ზემოდან ქვემოდან: SLO და p95 საფუძველზე - მიუთითეთ end-to-deadline, შემდეგ დაასხით Timauts.
2. „ძვირადღირებული“ ბილიკების იდენტიფიცირება (ფაილის დატვირთვა, მოხსენებები, გარე PSP) - ცალკეული გრძელი, მაგრამ შეზღუდული.
- idempotent (GET/სტატუსის გამეორება) - მოკლე, უფრო აგრესიული;
- write/ფულადი - ოდნავ გრძელი, მაგრამ ერთჯერადი გამეორებით და იდემპოტენტურობით.
4. დაგეგმეთ გეგმები/ტენანტები (enterprise- ს შეიძლება ჰქონდეს უფრო გრძელი ვიდრე timeout, მაგრამ უფრო მცირე პარალელიზმი).
4) Circuit breaker: მოდელები და პარამეტრები
4. 1 მუშაობის პოლიტიკა
Failure-rate: შეცდომების წილი X% N მოთხოვნის/დროის ფანჯარაში.
Consecutive failures: M ზედიზედ წარუმატებლობაა.
Slow-call: ზარების წილი უფრო გრძელია, ვიდრე T.
Error classes: Timauts/5xx/connection-reset, „ფატალური“, 4xx - არ არის გათვალისწინებული.
4. 2 მდგომარეობა
Closed - გამოტოვებს ყველაფერს, გროვდება სტატისტიკას.
ღია - მყისიერი უარი (დაზოგავს რესურსებს, არ ახდენს დამოკიდებულებას).
Half-Open - მცირე „ნიმუშები“ (N მოთხოვნა) „წყლის შემოწმებისთვის“.
4. 3 სასარგებლო დამატებები
Bulkhead (ჩარჩოები): ნაკადის/ნაერთების აუზი დამოკიდებულებისკენ ისე, რომ ერთმა არ „ჩამოაგდო“ ყველაფერი.
Adaptive currence: პარალელიზმის ავტომატური შეზღუდვა (AIMD/Vegas მსგავსი ალგორითმები) დაკვირვებული ლატენტობის შესაბამისად.
Load Shedding: ადრეული უარი/დეგრადაცია ადგილობრივი რესურსის ნაკლებობით (ხაზი, CPU, GC პაუზები).
5) ურთიერთქმედება: ტაიმაუტები, რეტრაები, ლიმიტები
ჯერ deadline, შემდეგ retries: თითოეული გამეორება უნდა განთავსდეს საერთო ვადაში.
Backoff + jitter გამეორებისთვის; პატივისცემა 'Retry-After' და retry-budget.
Rate limiting: ღია ყუთით - შეამცირეთ ლიმიტები ისე, რომ არ გაძლიერდეს ქარიშხალი.
Idempotence: სავალდებულოა write ოპერაციებზე (რათა თავიდან აიცილოთ დუბლი „ჩუმად“ ტაიმუთებში).
სად უნდა დახარჯოთ: სასურველია ზღვარზე (კლიენტი/კარიბჭე) და არა ღრმად შიგნით.
6) პრაქტიკული მიზნობრივი მნიშვნელობები (სახელმძღვანელო)
საზოგადოებრივი read API: end-end '200-500 ms', read timeout '100-300 ms'.
კრიტიკული write (გადახდები): '300-800 ms' e2e; გარე PSP '250-400 ms'.
Connect/TLS: '50-150 ms' (უფრო მეტი - ქსელის/ჭრილობის პრობლემა).
Idle: '30-90 s' (მობილური კლიენტები უფრო მოკლეა ბატარეის შესანახად).
შეასწორეთ მნიშვნელობები p95/p99 და რეგიონებში.
7) კონფისკაცია და მაგალითები
7. 1 Envoy (cluster + route, ფსევდო)
yaml clusters:
- name: payments_psp connect_timeout: 100ms type: STRICT_DNS lb_policy: ROUND_ROBIN circuit_breakers:
thresholds:
- priority: DEFAULT max_connections: 2000 max_requests: 2000 max_retries: 50 outlier_detection:
consecutive_5xx: 5 interval: 5s base_ejection_time: 30s max_ejection_percent: 50
routes:
- match: { prefix: "/api/v1/payments" }
route:
cluster: payments_psp timeout: 350ms # per-request deadline idle_timeout: 30s retry_policy:
retry_on: "reset,connect-failure,refused-stream,5xx,gateways"
num_retries: 1 per_try_timeout: 200ms
7. 2 NGINX (პერიმეტრი)
nginx proxy_connect_timeout 100ms;
proxy_send_timeout 200ms; # write proxy_read_timeout 300ms; # read
keepalive_timeout 30s;
send_timeout 15s;
Fast overload failure limit_conn_zone $ binary_remote_addr zone = addr: 10m;
limit_conn addr 50;
7. 3 GRPC (კლიენტი, Go-ფსევდო)
go ctx, cancel:= context. WithTimeout(context. Background(), 350time. Millisecond)
defer cancel()
resp, err:= client. Pay (ctx, req )//Deadline is passed down
7. 4 HTTP კლიენტი (Go)
go client:= &http. Client{
Timeout: 350 time. Millisecond ,//total deadline for inquiry
Transport: &http. Transport{
TLSHandshakeTimeout: 100 time. Millisecond,
ResponseHeaderTimeout: 250 time. Millisecond,
IdleConnTimeout: 30 time. Second,
MaxIdleConnsPerHost: 100,
},
}
7. 5 Resilience4j (Java, ფსევდო)
yaml resilience4j. circuitbreaker. instances. psp:
slidingWindowType: TIME_BASED slidingWindowSize: 60 failureRateThreshold: 50 slowCallDurationThreshold: 200ms slowCallRateThreshold: 30 permittedNumberOfCallsInHalfOpenState: 5 waitDurationInOpenState: 30s
resilience4j. timelimiter. instances. psp:
timeoutDuration: 350ms
8) დაკვირვება და ალერტინგი
8. 1 მეტრიკა
`http_client_requests{endpoint, status}`, `client_latency_bucket`
`timeouts_total{stage=connect|read|write|deadline}`
`circuit_state{dependency}`: 0/1/2 (closed/half/open)
`slow_call_rate`, `failure_rate`
`active_concurrency{route, dependency}`
`shed_requests_total{reason}` (load shedding)
`retry_total{reason}`, `retry_budget_used`
8. 2 ტრეისი
სპანები: ingress - handler - DB/Redis - გარე.
ატრიბუტები: 'timeout_ms_target', 'circuit_state', 'queue_time_ms'.
Exemplars: p99 მწვერვალების დაკავშირება კონკრეტულ trace-id- ზე.
8. 3 ალერტა
'p99_latency {critical}'> მიზნები X წუთი ზედიზედ.
'Timeout_rate {dependency}' ნახტომი> Y%.
ხშირი გადასვლები "ღია '/" flapping" breaker- ში.
ზრდა 'shed_requests_total' მაღალი CPU/GC- ით.
9) Adaptive Concurrency & Load Shedding
9. 1 იდეა
ავტომატიზაცია ამცირებს პარალელიზმს ლატენტობის კუდის ზრდის დროს:- AIMD: ნელა გაზრდა, მკვეთრად შემცირება.
- Vegas მსგავსია: მიზნობრივი რიგის შენარჩუნება.
- Token-based: თითოეული მოთხოვნა „იწვის“ ნიშანს; ნიშნები გაიცემა გაზომილი სიჩქარით.
9. 2 განხორციელება
ადგილობრივი per-route სემფორები; მიზანია ბარიერის ქვემოთ „queue_time“ შენარჩუნება.
გლობალური „დაუკრავენ“ (მაქსიმალური RPS/კონკურენტუნარიანობა) კარიბჭეზე.
CPU/ნაერთების ნაკლებობით - ლოგიკის შესრულების ადრეული უარყოფა (429/503 ერთად 'Retry-After').
10) ტესტირება და ქაოსის სცენარები
Latency injection: ხელოვნურად დაამატეთ 50-300 ms დამოკიდებულებაზე.
Packet loss/dup/drop (tc/tbf, Toxiproxy).
Knob turning: შეამცირეთ ნაერთების აუზები, გაზარდეთ დატვირთვა saturation.
Kill/Degrade ერთი ზონა/საშინელება (ნაწილობრივი მიუწვდომლობა).
შემოწმებები: არის თუ არა რეაგირების ქარიშხალი „ჩავარდნილი“; breaker იხსნება წინასწარ; რიგები იზრდება.
11) ანტიპატერები
ერთი გლობალური „read timeout“ კავშირის/TLS/პლეი-ეტაპის დეტალების გარეშე.
საერთო ვადის არარსებობა SLO- ს სცილდება.
Retries გარეშე jitter და გარეშე retry-budget.
„მარადიული“ ნაერთები idle Timauts- ის გარეშე - აღწერილობების გაჟონვა.
Breaker 4xx თვლის ფატალურ შეცდომებს.
არ არსებობს გაუქმება/abort, ფონის მუშაობა გრძელდება კლიენტის ტაიმუტის შემდეგ.
ძალიან გრძელი ტაიმაუტები მობილური/არასტაბილური ქსელებისთვის.
12) iGaming/ფინანსების სპეციფიკა
კრიტიკული write (ანაბრები/დასკვნები): ერთი მოკლე განმეორება Idempotency-Key- ით, შემდეგ '202 Accepted' + polling უსასრულო მოლოდინების ნაცვლად.
PSP/ბანკინგი: ცალკეული პროვაიდერის/რეგიონის პოლიტიკები (ზოგი უფრო ნელა).
პასუხისმგებელი გადასახადები და შეზღუდვები: დაბლოკვის/გამრავლებისას - სწრაფი „423/409“, არ გაჭიმოთ „ჩამოკიდებული“ ოპერაციები.
ანგარიში/აგრეგაცია - ასინქრონულად გაშვება (batch + სტატუსის რესურსი).
13) მზადყოფნის საკონტროლო სია
- განსაზღვრულია კრიტიკული მარშრუტების დასასრული (GET/POST).
- ბიუჯეტი დაიშალა ეტაპზე; ჩართულია ვადა.
- კონფიგურაცია/TLS/read/write/idle timauts კარიბჭეზე და კლიენტებზე.
- Circuit breaker failure-rate და slow-call ბარიერებით; სწორი ჰალფ-ღია ლოგიკა.
- Bulkheads დამოკიდებულია; პარალელიზმის ლიმიტები per-route.
- გადატვირთვის დროს ბიზნესის ლოგიკის შესრულებამდე.
- ინტეგრაცია რეაგირებით: backoff + gitter, retry-budget, პატივისცემა 'Retry-After'.
- write Idempotence, 'Idempotency-Key' და გარე მოვლენები.
- მეტრიკები: timeout/slow-call/breaker/queue time/კონკურენტუნარიანობა.
- ქაოსის ტესტები: შეფერხებების/ზარალის/წარუმატებლობის ინექცია, ზონების დეგრადაცია.
- დოკუმენტაცია მომხმარებლებისთვის: ტაიმინგის მაგალითები, პასუხის კოდები, გამეორების რჩევები.
14) TL; DR
მიეცით თითოეულ თხოვნას მკაცრი ვადა, განათავსეთ იგი ეტაპზე და გააფართოვეთ იგი ჯაჭვზე. აკონტროლეთ უარი circuit breaker + bulkheads + adaptive concurrency + load shedding- ის საშუალებით. განმეორებები - მხოლოდ ვადაზე, ჯიტერითა და ბიუჯეტით; write - მხოლოდ idempotent. გაზომეთ timeout/slow-call, breaker და 'queue_time' მდგომარეობა, რეგულარულად გაატარეთ ქაოსის ტესტები.