700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 「GoCN酷Go推荐」重试工具 — retry-go

「GoCN酷Go推荐」重试工具 — retry-go

时间:2022-07-09 02:12:22

相关推荐

「GoCN酷Go推荐」重试工具 — retry-go

简介

在微服务架构中,通常会有很多的小服务,小服务之间存在大量 RPC 调用,但时常因为网络抖动等原因,造成请求失败,这时候使用重试机制可以提高请求的最终成功率,减少故障影响,让系统运行更稳定。retry-go 是一个功能比较完善的 golang 重试库。

如何使用

retry-go的使用非常简单,直接使用Do方法即可。如下是一个发起 HTTP Get 请求的重试示例 :

url:="https://gocn.vip"varbody[]byteerr:=retry.Do(func()error{resp,err:=http.Get(url)iferr!=nil{returnerr}deferresp.Body.Close()body,err=ioutil.ReadAll(resp.Body)iferr!=nil{returnerr}returnnil},)fmt.Println(body)

调用时,有一些可选的配置项:

attempts最大重试次数

delay重试延迟时间

maxDelay最大重试延迟时间,选择指数退避策略时,该配置会限制等待时间上限

maxJitter随机退避策略的最大等待时间

onRetry每次重试时进行的一次回调

retryIf重试时的一个条件判断

delayType退避策略类型

lastErrorOnly是否只返回上次重试的错误

BackOff 退避策略

对于一些暂时性的错误,如网络抖动等,立即重试可能还是会失败,通常等待一小会儿再重试的话成功率会较高,并且这种策略也可以打散上游重试的时间,避免同时重试而导致的瞬间流量高峰。决定等待多久之后再重试的方法叫做退避策略。retry-go实现了以下几个退避策略:

func BackOffDelay

funcBackOffDelay(nuint,_error,config*Config)time.Duration

BackOffDelay 提供一个指数避退策略,连续重试时,每次等待时间都是前一次的 2 倍。

func FixedDelay

funcFixedDelay(_uint,_error,config*Config)time.Duration

FixedDelay 在每次重试时,等待一个固定延迟时间。

func RandomDelay

funcRandomDelay(_uint,_error,config*Config)time.Duration

RandomDelay 在 0 - config.maxJitter 内随机等待一个时间后重试。

func CombineDelay

funcCombineDelay(delays...DelayTypeFunc)DelayTypeFunc

CombineDelay 提供结合多种策略实现一个新策略的能力。

retry-go默认的退避策略为BackOffDelayRandomDelay结合的方式,即在指数递增的同时,加一个随机时间。

自定义的延时策略

下面是一个官方给出的例子,当请求的响应有Retry-After头时,使用该值去进行等待,其他情况按照BackOffDelay策略进行延时等待。

var_error=(*RetriableError)(nil)functest2(){varbody[]byteerr:=retry.Do(func()error{resp,err:=http.Get("URL")iferr==nil{deferfunc(){iferr:=resp.Body.Close();err!=nil{panic(err)}}()body,err=ioutil.ReadAll(resp.Body)ifresp.StatusCode!=200{err=fmt.Errorf("HTTP%d:%s",resp.StatusCode,string(body))ifresp.StatusCode==http.StatusTooManyRequests{//checkRetry-AfterheaderifitcontainssecondstowaitforthenextretryifretryAfter,e:=strconv.ParseInt(resp.Header.Get("Retry-After"),10,32);e==nil{//theserverreturns0toinformthattheoperationcannotberetriedifretryAfter<=0{returnretry.Unrecoverable(err)}return&RetriableError{Err:err,RetryAfter:time.Duration(retryAfter)*time.Second,}}//Arealimplementationshouldalsotrytohttp.ParsetheretryAfterresponseheader//toconformwithHTTPspecification.Hereinweknowherethatwereturnonlyseconds.}}}returnerr},retry.DelayType(func(nuint,errerror,config*retry.Config)time.Duration{fmt.Println("Serverfailswith:"+err.Error())ifretriable,ok:=err.(*RetriableError);ok{fmt.Printf("Clientfollowsserverrecommendationtoretryafter%v\n",retriable.RetryAfter)returnretriable.RetryAfter}//applyadefaultexponentialbackoffstrategyreturnretry.BackOffDelay(n,err,config)}),)fmt.Println("Serverrespondswith:"+string(body))}

总结

重试可以提升服务调用的成功率,但重试时也要警惕由此带来的放大故障的风险。选择合适的退避策略,控制放大效应,才能优雅的提升服务的稳定性。

Reference

如何优雅地重试-InfoQ

[译] 重试、超时和退避 | nettee 的 blog

《酷Go推荐》招募:

各位Gopher同学,最近我们社区打算推出一个类似GoCN每日新闻的新栏目《酷Go推荐》,主要是每周推荐一个库或者好的项目,然后写一点这个库使用方法或者优点之类的,这样可以真正的帮助到大家能够学习到

新的库,并且知道怎么用。

大概规则和每日新闻类似,如果报名人多的话每个人一个月轮到一次,欢迎大家报名!戳「阅读原文」,即可报名

扫码也可以加入 GoCN 的大家族哟~

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。