重试机制的实现
文章目录
服务在请求资源,如果遇到网络异常等情况,导致请求失败,这时需要有个重试机制来继续请求。 常见的做法是重试3次,并随机 sleep 几秒。 业务开发的脚手架,HTTP Client 基本会封装好 retry 方法,请求失败时根据配置自动重试。下面以一个常见的 HTTP Client 为例, 看下它是如何实现请求重试。 最后整理其他一些重试机制的实现。
go-resty 重试机制的实现
先看下 go-resty 在发送 HTTP 请求时, 请求重试的实现:
|
|
重试流程
梳理 Execute(method, url)
在请求时的重试流程:
- 如果没有设置重试次数,执行
r.client.execute(r)
:直接请求 Request , 返回 Response 和 error。 - 如果
r.client.RetryCount
不等于0 ,执行Backoff()
函数 Backoff()
方法接收一个处理函数参数,根据重试策略, 进行 attempt 次网络请求, 同时接收Retries()、WaitTime()
等函数参数
Backoff函数
重点看下 Backoff()
函数做了什么动作。
Backoff()
代码如下:
|
|
梳理 Backoff()
函数的流程:
Backoff()
接收 处理函数 和 可选的 Option 函数(retry optione) 作为参数- 默认策略3次重试, 通过 步骤一 预设的 Options, 自定义重试策略
- 设置请求的 repsonse 和 error 变量
- 开始进行
opts.maxRetries
次 HTTP 请求:- 执行处理函数 (发起 HTTP 请求)
- 如果返回结果不为空并且 context 不为空,保持 repsonse 的请求上下文。 如果上下文出错, 退出
Backoff()
流程 - 执行
retryConditions()
, 设置检查重试的条件。 - 根据 needsRetry 判断是否退出流程
- 通过
sleepDuration()
计算 Duration(根据此次请求resp, 等待时间配置,最大超时时间和重试次数算出 sleepDuration。 时间算法相对复杂, 具体参考: Exponential Backoff And Jitter) - 等待 waitTime 进行下个重试。 如果请求完成退出流程。
一个简单的 Demo
看具体 HTTP Client (有做过简单封装)的请求:
|
|
根据以上梳理的 go-resty 的请求流程, 因为 RetryCount
大于0,所以会进行重试机制,重试次数为3。然后 request.Get(url)
进入到 Backoff()
流程,此时重试的边界条件是: !response.IsSuccess()
, 直到请求成功。
一些其他重试机制的实现
可以看出其实 go-resty 的 重试策略不是很简单, 这是一个完善,可定制化, 充分考虑 HTTP 请求场景下的一个机制, 它的业务属性相对比较重。
再来看看两个常见的 Retry 实现:
实现一
|
|
每次重试等待随机延长的时间, 直到 f()
执行完成 或不再重试。
实现二
|
|
对函数重试 attempts 次,每次等待 sleep 时间, 直到 f()
执行完成。