使用指数回退算法重试请求
我们在搭建自己的服务的时候,同时会用到一些第三方服务的api,这些api可能会有速率的限制,这个时候,我们就需要控制我们的发送请求的速率,有很多种方法,比如我们直接计算出来每秒最多请求几次,然后做一些精细化的控制,当然我们也有比较简单粗暴但是行之有效的方法,就是等一会儿再请求,这就是指数回退算法。
算法实现
下面是使用 TypeScript 实现的函数,该函数可以使用指数回退算法重试抛出指定错误的请求:
1 | async function retryWithExponentialBackoff<T>(request: () => Promise<T>, errorType: any, maxRetries: number, initialDelay: number, maxDelay: number): Promise<T> { |
这个函数接受以下参数:
request
:一个返回 Promise 的函数,表示要重试的请求。errorType
:要捕获并重试的错误类型。maxRetries
:最大重试次数。initialDelay
:初始延迟时间(毫秒)。maxDelay
:最大延迟时间(毫秒)。
函数会在每次请求失败时捕获指定的错误类型,并使用指数回退算法进行重试。重试的次数将根据 maxRetries
参数确定,初始延迟时间为 initialDelay
,每次重试后的延迟时间将加倍,但不会超过 maxDelay
。
如果达到最大重试次数仍然失败,函数将抛出一个错误。
以下是一个示例用法:
1 | // 模拟一个可能会失败的请求 |
在上面的示例中,makeRequest
函数模拟了一个可能会失败的请求。我们使用 retryWithExponentialBackoff
函数对该请求进行重试,最大重试次数为 3,初始延迟时间为 1000 毫秒,最大延迟时间为 5000 毫秒。
如果请求成功,将输出 Request succeeded with result: 42
;如果重试次数达到上限仍然失败,将输出类似于 Request failed after retries: Max retries (3) exceeded.
的错误信息。
优缺点
优点比较明显,就是简单,重试就完事了,不过每次重试失败都会让下一次的重试来得更晚,就导致了没有可能会有“饿死”的现象,也没有办法通过优先级去控制