LabHub
学习 学习路径 课程

集成与部署

超时之后再重试,会发生什么

在 LabHub 中继续学习

一句话总结

超时不是请求失败的意思,而是不知道结果的意思。 如果错过了这个差异,重新尝试会造成重复结算和重复发送。

流程图: 请求失败 · 不知道结果 · 两次批准 · 不确定的结果(indeterminate)

为什么需要这个?

结算关联中最常见的事故是这样的。

  1. 我们发送了结算请求
  2. 3秒超时——没有回复
  3. 看来失败了,再试一次
  4. 在结算公司两次批准

3次的判断是错误的。没有收到回复和没有处理是不同的。 请求已经到达,处理也完成了,可能只有回复丢失了。

在分布系统中,这个被称为不确定的结果(indeterminate)。 不是成功也不是失败,而是第三种状态,处理这种状态的方法是不同的。

可以重试和不能重试的东西

核心问题是**“这个运算是等价的吗”**。即使两次发送相同的请求 如果结果和第一次发送的一样,那就毫无意义了。

计算 错误? 重新尝试
GET /orders/123 是的 自由地
PUT /orders/123 {status:"PAID"} 是的(用相同的值) 安全
DELETE /orders/123 是的(没有第二个) 安全
POST /orders {…} 危险 — 需要安全带
POST /payments {amount:1000} 危险
扣除余额balance -= 1000 危险

HTTP方法的兼容性是规范,而不是保证。服务器PUT从 增加计数器的话,那个PUT不是很重要。不是文件 需要确认动作

橙色钥匙

为了安全地重新尝试不正确计算的运算,客户端每次请求时 制作一个唯一的密钥发送给你。

POST /payments
Idempotency-Key: 3f9a1c7e-2b44-4c9d-a1f8-0d6e2b7c5a11
{"order_id": 123, "amount": 1000}

服务器会保存这个密钥,如果用同样的密钥再次访问,**不会重新处理。 将保存的结果原封不动地退还给您。**无论尝试几次,结算一次。

制作密钥时有需要注意的地方。重新尝试时必须使用相同的密钥。 每次尝试都创建新的UUID的话毫无意义。键是“这个业务 关于“行为”是一个,关于“这个HTTP请求”不是一个。

重新尝试政策

随便重新尝试的话会增加障碍。下游很慢,所以超时了。 如果全部立即重新尝试,负载就会增加一倍,完全崩溃。

然后区分要重试哪些错误

回复 重新尝试
拒绝连接,超时 否(当有闪烁或闪烁键时)
429 Too Many Requests 是 —Retry-After遵守
500、502、503、504 一般是
400, 422(请求错误) — 无论发送多少次都一样
401, 403 否 — 需要修改资格证明

调查时的信号

如果怀疑有重复,请这样查找。

SELECT order_id, count(*) FROM payments
GROUP BY 1 HAVING count(*) > 1;

还有那些重复的件子的created_at看看间隔。间隔和重新尝试后退 如果相似的话(1秒、2秒、4秒),原因几乎确定了。

重新尝试增加障碍的方式

如果再试用得当,可以掩盖暂时性的失败;如果使用不当,**小障碍会变成大障碍。 培养。**培养的路线是确定的。

每层重新尝试的话会乘以。客户3次,网关3次,服务 如果尝试3次,一次用户请求就会以27次的负载到达上游。上游 开始缓慢的事情会让上层更慢。原则是只在第一层重新尝试 是,通常与用户最近的楼层是那个位置。

如果以相同的间隔重新尝试的话,就会变成波浪。障碍中失败的请求正好1秒 后面一次性回来。本想恢复的服务再次淹没在波浪中。智秀 在白化上混合随机震动的理由就是这个。

delay = min(cap, base * 2 ** attempt) * (0.5 + random.random() * 0.5)

如果没有断路器,重新尝试不会停止。 上游完全死掉的时候 再试无意义,只会消耗资源。失败率超过临界值时,暂时试行本身 停止,偶尔只发送一个,确认恢复。快速失败对用户来说也是 好多了 — 比起等了30秒后的错误,立即出现的错误更容易重试。

**传播期限(deadline)。**如果用户等待5秒,该请求就会过期。 所有区间都需要知道剩余的时间。剩余时间是200ms,但3秒的呼叫 重新开始是浪费。gRPC的deadline或通过头信息传递的到期时间各 确认楼层。

不会再次尝试无法重试的错误。 400·401·404·409 会重试几次 也可以发送。值得再试的只有429·502·503·504和连接错误, 在429中Retry-After因为附着着,所以保持那个价值。

**对于重新尝试的请求,会留下标记。**在日志和头中放入尝试编号的话,障碍 在调查中,将“请求增加了3倍”分为用户增加了还是重新尝试。

在现场相遇的样子

在接下来的实习中要做的事情

针对处理完毕但只丢失响应的结算API进行三次结算。

멱등키 없이             주문 4건 → 기록 7건
비즈니스 행위당 키 하나   주문 4건 → 기록 4건
시도마다 새 키           주문 4건 → 기록 7건   ← 키를 붙였는데도 소용없다

第三个是这个实训的核心。光是贴上钥匙的事实就什么都不能 不保证。