LabHub
学习 学习路径 课程

微服务架构

给服务间 REST 调用加上超时与重试

在 LabHub 中继续学习

目标

针对不稳定的下游,直接实现超时、指数倒退、震动、禁止重试条件、重置,完成同步调用的基本技能。

为什么重要

在同步调用中,错误通常归因于“没有超时”或“错误地重试”。如果没有超时,当下游变慢时,上游的连接池会先用完,甚至连与下游无关的请求也会失败。相反,如果无限地以固定的间隔重试,每次下游试图恢复时都会被同样的波浪覆盖。在实际案例中,一个订单实例每秒处理20多个请求,以maxAttempts 5重试后,支付服务每秒处理了10,000个请求。重试不是增加负载,而是乘以负载。因此,这个练习重视输入值的顺序——首先是超时,然后是重试条件,然后是后退和震动,最后是恢复。

阶段

  1. /opt/app/flaky.py将 127.0.0.1:8110 启动。GET /fast要去200。
  2. /root/rest/call.py制作/fast呼叫并回复正文/root/rest/fast.out保存到。
  3. /root/rest/timeout.py制作/slow以1.0秒超时调用。/root/rest/timeout.out在第一行TIMEOUT,在第二行elapsed=<초>写。时间不得少于2.0秒。
  4. /root/rest/retry.py制作/flaky?key=lab&fail=2重新尝试了95%的概率,最终成功了。/root/rest/retry.logattempt=<n> wait=<초>以形式为准,每次尝试留下一行,共3行。
  5. retry.py将等待计算改为full jitter。抽取尝试编号2的等待时间20次/root/rest/jitter.txt逐行写一行。不同值必须超过15个。
  6. /root/rest/retry400.py/bad呼叫。400不会再尝试,所以/root/rest/retry400.log必须是准确的1行。
  7. /root/rest/budget.txtinstances=20rps=100max_attempts=5worst_rps=10000写四行。
  8. /root/rest/gateway.py将 127.0.0.1:8111 启动。GET /order是下游/always500呼叫,但适用超时和重新尝试,最终失败时200和{"degraded":true}给。

参考

不稳定的下游浮动

/opt/app/flaky.py将 127.0.0.1:8110 启动。GET /fast要去200。

执行/opt/app/flaky.py后会显示8110。请先用眼睛确认/fast、/slow、/flaky、/bad四个路线的运行情况。

以正常呼叫为基准线设定基准线

/root/rest/call.py制作/fast呼叫并回复正文/root/rest/fast.out保存到。

httpx 使用 urllib 调用 /fast,并将正文保存为文件。现在不用担心超时。

将缓慢的响应以超时方式中断

/root/rest/timeout.py制作/slow以1.0秒超时调用。/root/rest/timeout.out在第一行TIMEOUT,在第二行elapsed=<초>写。时间不得少于2.0秒。

/slow会在3秒后回复。如果将客户端超时时间设置为1秒,就会发生异常。捕获异常,并一起记录结果和持续时间。

实现指数百折扣重新尝试

/root/rest/retry.py制作/flaky?key=lab&fail=2重新尝试了95%的概率,最终成功了。/root/rest/retry.logattempt=<n> wait=<초>以形式为准,每次尝试留下一行,共3行。

每次尝试的间隔都翻倍。每个尝试的编号和等待时间都必须在日志中留下一行才能得分。

用震动重新尝试时点的分散

retry.py将等待计算改为full jitter。抽取尝试编号2的等待时间20次/root/rest/jitter.txt逐行写一行。不同值必须超过15个。

full jitter等待从0开始计算的backoff之间的随机数。即使在同一尝试编号下,值也必须每次都不同。

对于确定的错误,不要再试一次。

/root/rest/retry400.py/bad呼叫。400不会再尝试,所以/root/rest/retry400.log必须是准确的1行。

400无论发送多少次都是400。请插入状态代码来区分是否重新尝试的分支。

重新尝试预算计算

/root/rest/budget.txtinstances=20rps=100max_attempts=5worst_rps=10000写四行。

实例数x每秒请求数x最大尝试数是下游接收的最差每秒请求数。请分别写下三个值和结果。

综合为有翻盖的门户

/root/rest/gateway.py将 127.0.0.1:8111 启动。GET /order是下游/always500呼叫,但适用超时和重新尝试,最终失败时200和{"degraded":true}给。

即使下游死机,也给用户200,但会在响应中留下质量下降的标记。同时写入前一步的超时和重试。