Διακόπτης και υποχώρηση κυκλώματος
Διακόπτης κυκλώματος και Retrai
1) Γιατί το χρειάζεστε
Τα δίκτυα είναι αναξιόπιστα: οι παλμοί καθυστέρησης, οι κόμβοι πέφτουν, τα όρια επιτυγχάνονται. Τα retrays σώζονται από βραχυπρόθεσμες αποτυχίες, και το Circuit Breaker προστατεύει το σύστημα από τις αστοχίες και το self-DDoS. Ο συνδυασμός με τα σωστά χρονικά περιθώρια και τα όρια διατηρεί το SLO, σταθεροποιεί τις καθυστερήσεις στην ουρά και την τιμή των «εννιάρια».
2) Βασικές αρχές
Πρώτα τα timeouts, μετά τα retreats και μετά το Circuit Breaker.
Ανασύσταση μόνο idempotent λειτουργίες (GET, ασφαλές POST/PUT με idempotent κλειδί).
Διάθεση προϋπολογισμού επανακαταμέτρησης: ≤ 10-15% της αρχικής RPS ανά διαδρομή.
Αστοχία εντοπισμού: διάφραγμα (χωριστές ομάδες/ποσοστώσεις) + όριο ταχύτητας.
Κατά τη διάρκεια της αποικοδόμησης - ταχεία αστοχία (αστοχία), χαριτωμένη-αποικοδόμηση/απόκομμα.
3) Retray σημασιολογία
Πότε να υποχωρήσετε
Παροδικά σφάλματα: timeouts, 5xx, μη διαθεσιμότητα δικτύου, 429 (μετά το 'Retry-After').
Δεν μπορείτε να αποσύρετε: προφανή επιχειρηματικά σφάλματα (4xx ≠ 429), παρενέργειες χωρίς ταυτότητα (πληρωμή χωρίς κλειδί).
Στρατηγικές
Εκθετικό backoff + jitter (πλήρης ή ακόμη): Smooths έξω σμήνη των retraces.
Max απόπειρες: 1-2 (σπάνια 3) - περισσότερες είναι συνήθως επιβλαβείς.
Προϋπολογισμός: συνολικός μετρητής επαναπροσδιορισμού/sec ανά υπηρεσία και ανά αίτηση «μάρκες επαναπροσδιορισμού».
Αντιστάθμιση (σπάνια): παράλληλο διπλό της αίτησης μετά το t-quantile (p95) - μόνο για αυστηρά idempotent reads.
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) Χρονοδιαγράμματα και «γρήγορη αποτυχία»
Timeout πελάτη <upstream timeout: ώστε να μην συσσωρεύονται αιτήματα «zombie».
: σύνδεση timeout, ανάγνωση timeout, συνολική προθεσμία.
Timeouts: στόχος για p95/p99 + μικρό περιθώριο.
Χρησιμοποιήστε ένα κοινό χρονοδιάγραμμα (για παράδειγμα, «προθεσμία» gRPC) και ρίξτε το στην αλυσίδα.
5) Διακόπτης κυκλώματος: Πώς λειτουργεί
Κράτη:- Κλειστό: περνά την κυκλοφορία, μετρά τα σφάλματα/καθυστέρηση.
- Άνοιγμα: αμέσως δίνει μια γρήγορη άρνηση (ή ανταλλακτική απάντηση).
- Half-Open: ερωτήσεις δοκιμής. εάν είναι επιτυχής, κλείνει.
- Σφάλματα/χρονοδιαγράμματα υπερβαίνουν το X% ανά αίτημα/δευτερόλεπτα παραθύρου N ή το p99 πάνω από το κατώφλι.
- Οι κυλιόμενες στατιστικές και ο ελάχιστος όγκος είναι συναφείς (π.χ. ≥ 50 ερωτήματα).
6) Διάφραγμα, ποσοστώσεις και διαίρεση και κατάκτηση
Χωριστές ομάδες συνδέσεων per-upstream και per-feature.
Ποσοστώσεις για αιτήσεις πτήσης περιττή - γρήγορη άρνηση.
Σε περίπτωση έλλειψης - υποβάθμιση σημαιών χαρακτηριστικών.
7) Περιμετρική ολοκλήρωση (Απεσταλμένος/Istio/Nginx)
Απεσταλμένος (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, συμπιεσμένο παράδειγμα):
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) Βιβλιοθήκες και κωδικός (στοίβα snippets)
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 (προθεσμία πλαισίου + 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() }
Κόμβος. 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) Προϋπολογισμός Retray και SLO
Κάθε επανασυσκευασία ξοδεύει ένα σύμβολο. η κοινοπραξία είναι περιορισμένη.
Συσχετίστε με τον προϋπολογισμό σφάλματος: εάν ο ρυθμός καύσης είναι πάνω από το όριο, απενεργοποιήστε τις επανασυνδέσεις, ανοίξτε τις ΚΤ συχνότερα, ενεργοποιήστε την αποικοδόμηση.
Canary releases: Στα καναρίνια, μειώστε τις προσπάθειες και τις μάρκες.
10) Αντιστάθμιση κινδύνου (προσοχή)
Εκτελέστε ένα επιπλέον αίτημα μετά την προθεσμία του p95, ακυρώνοντας τον ηττημένο.
Μόνο για αναγνωστικές και «ασφαλείς» λειτουργίες. περιορισμός του μεριδίου (≤ 1-5%).
Προσέξτε να αυξηθεί το φορτίο στα ανάντη.
11) Παρατηρησιμότητα
Μετρήσεις RED κατά μήκος των διαδρομών: ρυθμός, σφάλμα, διάρκεια (p50/p95/p99).
Μετρήσεις ΚΤ: κατάσταση (ανοικτή/ημι-ανοικτή), ποσοστό ανοίγματος, αποτυχημένα/απορριφθέντα αιτήματα.
Retrays: απόπειρες/αίτημα, retry-rate, καμένες μάρκες.
Περίμετρος: πιο ακραία εκτίναξη, ρυθμός εκτίναξης.
Traces: σχολιάστε 'retry _ try', 'cb _ state', 'hedged = true', cast 'trace _ id'.
12) Ολοκλήρωση της αρχιτεκτονικής
Διάφραγμα + CB για κάθε κρίσιμο ανάντη.
Ουρές ουράς/asynchron: για μεγάλες λειτουργίες αντί για τρελά timeouts.
Cache/stubs: για μη κρίσιμα χαρακτηριστικά όταν ανοίγει η μνήμη.
Αυτόματη κλίμακα: Δεν επανορθώνει για κακές υποχωρήσεις - σταματήστε πρώτα την καταιγίδα.
13) Αντι-μοτίβα
Retrays χωρίς χρονοδιαγράμματα → παγωμένες συνδέσεις και εξάντληση των δεξαμενών.
Επαναλάβετε μη ευέλικτες συναλλαγές (διπλές διαγραφές).
Άπειρη εκθετική ανάπτυξη χωρίς καπάκι και νευρικότητα.
Μία μόνο ΚΤ σε όλα τα ανάντη → σύρετε και ρίξτε την αποτυχία σε ολόκληρο το προϊόν.
Αγνοώντας το 429/' Retry-After '.
Το χρονικό περιθώριο του πελάτη είναι μεγαλύτερο από εκείνο του προηγούμενου σταδίου (ή καθόλου).
«Αντιμετώπιση» επιχειρηματικών σφαλμάτων με ρετρά.
14) Κατάλογος ελέγχου εφαρμογής (0-30 ημέρες)
0- 7 ηµέρες
Προσδιορισμός των διαδρομών και της ταυτότητάς τους.
Ορισμός χρονοδιαγραμμάτων (σύνδεση/ανάγνωση/σύνολο), ενεργοποίηση ελάχιστων επαναλήψεων (× 1) και προεπιλεγμένων CB.
Διαχωρισμός των κοινοπραξιών/ποσοστώσεων (διαφραγμάτων) για το κύριο ανάντη.
8- 20 ημέρες
Συμπεριλαμβάνονται ειδοποιήσεις επανάληψης και συνολικός προϋπολογισμός επαναπροσδιορισμού.
Ρύθμιση εξερχόμενης εκτίναξης στην περίμετρο, γρήγορη αποτυχία για λειτουργία χαμηλού prio.
RED + CB/Retry ταμπλό, πινακίδες.
21- 30 ημέρες
Προφίλ Canary retray (λιγότερες προσπάθειες), παιχνίδι-ημέρα «ανάντη αργή/πτερύγια».
Πολιτική εγγράφων: ποιος/τι επαναπροσδιορίζει, όρια, εξαιρέσεις.
Ανασκόπηση του p95/p99 και των χρονοδιαγραμμάτων σύμφωνα με τα δεδομένα, όχι με το μάτι.
15) Μετρήσεις διάρκειας
Το 100% των διαδρομών έχουν χρονοδιαγράμματα και τεκμηριωμένη πολιτική επαναπροώθησης/ΜΝ.
Το ποσοστό επαναπροσδιορισμού εντάσσεται στον προϋπολογισμό (≤ 10-15%), δεν υπάρχουν αυξήσεις στα περιστατικά.
πυρκαϊά CB πριν από την πτώση ολόκληρης της δεξαμενής· καμία αστοχία κατακράτησης.
Τα μονοπάτια δείχνουν απόπειρες/αντιστάθμιση κινδύνου. Το p99 είναι σταθερό στις κορυφές.
Οι κυκλοφορίες καναρινιών χρησιμοποιούν ένα «προσεκτικό» προφίλ επαναπροσδιορισμού.
16) Παραδείγματα σύντομης διαμόρφωσης
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
Όριο ποσοστού των απεσταλμένων (τμήμα ιδέας):
yaml rate_limits:
- actions:
- generic_key: { descriptor_value: "api. payments" }
17) Συμπέρασμα
Η βιωσιμότητα είναι μια πειθαρχία: timeouts → retreats (με νευρικότητα και προϋπολογισμό) → Circuit Breaker + διάφραγμα/ποσοστώσεις και γρήγορη απόρριψη. Δημιουργήστε μια περίμετρο (εξωγήινη εκτίναξη), κλείστε τα ταμπλό RED/CB/Retry, καθορίστε την πολιτική της ευφυΐας και μην ξεχνάτε τις επιχειρήσεις SLI. Στη συνέχεια, οι σύντομες αποτυχίες θα παραμείνουν αόρατες και τα πραγματικά περιστατικά δεν θα μετατραπούν σε καταρρακτώδεις πτώσεις.