GH GambleHub

Circuit Breaker和Retrai

Circuit Breaker and Retrai

1)为什么需要它

网络不可靠:潜伏脉冲,节点下降,达到极限。Retrai可以避免短暂的故障,而Circuit Breaker可以保护系统免受级联故障和"samo-DDoS"的影响。与正确的计时器和限制相结合,可以保持SLO,稳定尾部延迟和"九"价格。

2)基本原则

首先是taymauts,然后是retrai,然后是Circuit Breaker。
仅恢复偶数操作(GET,具有偶数键的安全开机/PUT)。
拨出转发预算:每条路线≤原始RPS的10-15%。
本地化故障:bulkhead(分离池/配额)+rate-limit。
降解-快速故障(fail-fast), graceful-degradation/存根。

3)Retrae语义

何时回荡

过境错误:timeouts,5xx,网络不可用,429(在"Retry-After"之后)。
您不能转发:显式业务错误(4 xx ≠ 429), side-effects没有等效性(无钥匙付款)。

策略

Exponential backoff+jitter(完整或均匀):平滑背包。
Max attempts:1-2(很少3)-通常更有害。
Budget:全球每种服务的转发/秒计数器和per-request "retry tokens"。
Hedging(很少):t-quantili (p95)后并行查询复制-仅用于严格等效阅读。

伪代码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)Taymauts和"快速拒绝"

Client timeout <upstream timeout:不要挖掘"僵尸"查询。

Делите: connect timeout, read timeout, overall deadline.

Tail-aware定时器:我们瞄准p95/p99+少量库存。
使用共享的截止日期字段(例如gRPC"截止日期")并沿着链条向下推。

5) Circuit Breaker: 如何工作

状态:
  • Closed:跳过流量,计算错误/潜伏期。
  • 打开:立即发出快速故障(或备用响应)。
  • 半场开放:验证请求;成功时-关闭。
开口阈值:
  • 错误/时间间隔超过了N查询/秒窗口的X%分数,或高于阈值的p99。
  • 相关的滚动统计数据和最小体积(例如,≥ 50个查询)。

6)Bulkhead,配额和"分而治之"

上游和上场连接的分离子弹。
航班查询配额;更多的是快速拒绝。
在短缺的情况下-低优先级Fitch降解(功能标记)。

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)图书馆和代码(堆栈扫描)

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

输入复古令牌:每个复古花费令牌;池有限。
与error-budget连接:在高于阈值的burn-rate-禁用转发,更频繁地打开CB,包括降解。
金丝雀发行版:在金丝雀上,减少尝试和令牌。

10)起床(小心)

在p95截止日期后触发附加请求,取消失败者。
仅用于阅读和"安全"等效操作;限制份额(≤ 1-5%)。
留意加速负载的增加。

11)可观察性

路线上的RED度量:Rate、Error、Duration (p50/p95/p99)。
CB度量:状态(开放/半开放),发现频率,遗漏/拒绝的请求。
Retrai:attempts/request,retry-rate,燃烧的令牌。
周长:outlier-ejection, ejection-rate。
Traces:注释"retry_attempt"、"cb_state"、"hedged=true"、"trace_id"。

12)与体系结构集成

Bulkhead+CB对于每个关键的应用。
队列/asinchron:用于长时间操作而不是疯狂的taymout。
Kesh/存根:对于失误打开时非关键的幻灯片。
Autoscale:不补偿不良的撤退-首先停止"风暴"。

13)反模式

没有Taymout的Retrai →"悬停"的连接和池的耗尽。
重复非偶数操作(双重注销)。
无穷大的指数增长,没有帽子和挤压器。
单个CB到所有apstrims →将故障拖到整个产品上。
忽略了429/"Retry-After"。
客户的定时时间比apstrim(或根本没有)更长。
"治疗"回避业务错误。

14)实施清单(0-30天)

0-7天

确定路线及其相容性。
设置计时器(connect/read/overall),启用最小retrai (× 1)和默认的CB。
将基本应用程序的池/配额(bulkhead)分开。

8-20天

包括jitter和retrais的全球预算,alerta按重复率。
在外围设置直截了当-ejection,快速故障以实现低价。
RED+CB/Retry dashboards,带标签的预告片。

21-30天

金丝雀轮廓retrais(尝试较少),游戏日"慢速/轻浮"。
记录政策:谁/什么是复述,限制,例外。
根据数据而不是眼睛修改p95/p99和taymout。

15)成熟度量

100%的路线都有taymauts和有记录的retrais/SV政策。
Retry-rate符合预算(≤ 10-15%),事件中没有激增。
CB的触发时间比整个池都早。没有级联故障。
Traces显示尝试/抱怨;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)结论

可持续性是一门学科:taymauts → retrai(带有抖动和预算的)→ Circuit Breaker+bulkhead/配额和快速豁免。设置外围(outlier-ejection),挂起RED/CB/Retry行车记录板,记录等效性策略,不要忘记业务SLI。然后,短暂的失败将保持不变,实际事件不会变成级联下降。

Contact

联系我们

如需任何咨询或支持,请随时联系我们。我们随时准备提供帮助!

Telegram
@Gamble_GC
开始集成

Email — 必填。Telegram 或 WhatsApp — 可选

您的姓名 可选
Email 可选
主题 可选
消息内容 可选
Telegram 可选
@
如果填写 Telegram,我们也会在 Telegram 回复您。
WhatsApp 可选
格式:+国家代码 + 号码(例如:+86XXXXXXXXX)。

点击按钮即表示您同意数据处理。