-
Notifications
You must be signed in to change notification settings - Fork 167
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
重试机制:自适应重试控制策略 #269
Comments
用 ReportAndNext 还是用 Next,我觉得可以稍微讨论一下。如果你不想讨论,就用 Next(ctx context.Context, err error) (time.Duration, bool) |
这里用Next会好一些,增加ReportAndNext 接口变复杂了,需要额外理解 ReportAndNext 和 Next 的区别,而且两个方法功能有重叠的,不如一了白了,都统一设计 |
可以只用 Next。我在想的是,如果是 Next 传入了 ctx 之后,我的 retry.Retry 方法不就是很没用了吗?因为我可以直接在实现 Next 的时候就直接阻塞了,都不需要返回 time.Duration |
要么再显示支持wait 方法 |
第二种,就是传ctx就传,不管就行了,说明只返回时间戳 |
第三种,直接废弃 retry.Retry 😂 |
就用这个: Next(ctx context.Context, err error) (time.Duration, bool) |
仅限中文
使用场景
在超时的情况下,我们一般会考虑使用重试策略。但是重试会有一个问题:如果超时本身是因为高负载引起的,那么重试就会进一步加重这个系统负担。
所以实际上在重试的时候要区别是偶发性超时还是频繁超时。
为了达成这个目标,一种比较简单的做法是借助滑动窗口算法统计窗口内超时请求的比率。如果超时请求已经超过一定比率了,那么就不需要重试了。
可行方案
我们需要一个新的装饰器,这个装饰器只用来判定要不要执行重试,具体重试间隔,重试次数上限交给被装饰的来解决。整个结构体定义如下:
并且,我们这个方案必然是用在高并发场景下的——低并发场景你无脑重试就可以了,不存在什么系统负载高的问题。
因此为了节省磁盘空间,我们使用比特级别的 ring buffer 来实现。在整个实现里面,使用 n 个 byte 来作为环,也就是说有 8 * n 个比特。而后,如果一个请求过来,超时了,那么就把对应的比特位标记为 1。如果没超时,那么就标记为 0。
每次要重试的时候,就需要计算一下这些 byte 里面有多少个比特是 1,而后和 threshold 进行比较。如果超过了 threshold,那么就不能执行重试了。
但是在我们已有的接口设计中有一个小问题,就是 Next 方法不接收任何参数,所以为了适配这个,需要额外提供一个方法来上传它的执行结果并且询问下一个要不要执行重试。
在这种情况下,暂时定义一个新的方法:
其它
这种设计会有一个问题,我们无法把 AdaptiveTimeoutRetryStrategy 传入到 retry.Retry 方法里面。所以另外一个可行的考虑是直接引入一个不兼容的变更,将 Next 方法改为:
当然这对于我们来说就好多了,不过用户就要修改代码了。我个人认为其实我们的用户也不是很多,所以这样改也不是不可以。
你使用的是 ekit 哪个版本?
你设置的的 Go 环境?
The text was updated successfully, but these errors were encountered: