项目场景:
服务之间的调用可能会出现一些无法访问或者超时等错误,有时候需要重试机制来解决问题
application.properties配置:
#ribbon单独配置 springboot 2.4.x的版本无法使用(后续loadbalancer可能是主流会逐渐替换ribbon)
#ribbon本地配置服务列表,没有使用注册中心 OrchestrationClient为服务名
OrchestrationClient.ribbon.listOfServers=http://127.0.0.1:22114,http://127.0.0.1:22115,http://127.0.0.1:22116
#自定义负载策略 这里是轮询策略,ribbon提供的很多种轮询策略,可以根据需要自行配置
OrchestrationClient.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RoundRobinRule
#对所有的操作进行重试
OrchestrationClient.ribbon.OkToRetryOnAllOperations=true
#连接超时
OrchestrationClient.ribbon.ConnectTimeout=6000
#读取超时
OrchestrationClient.ribbon.ReadTimeout=5000
#重试次数相关配置
OrchestrationClient.ribbon.MaxAutoRetries=1
OrchestrationClient.ribbon.MaxAutoRetriesNextServer=2
上面的针对某个服务配置的ribbon属性,相关属性都可以在com.netflix.client.config.DefaultClientConfigImpl这个类里面找到
重试调用次数底层的判断:
底层请求调用的执行是由RetryTemplate里面的execute方法来操作的,当调用出错的时候,会捕获异常并做相应处理,然后会循环重试,循环调用次数的判断在这个类RibbonLoadBalancedRetryPolicy里面,源码如下
@Override
public void registerThrowable(LoadBalancedRetryContext context, Throwable throwable) {
// if this is a circuit tripping exception then notify the load balancer
if (lbContext.getRetryHandler().isCircuitTrippingException(throwable)) {
updateServerInstanceStats(context);
}
// Check if we need to ask the load balancer for a new server.
// Do this before we increment the counters because the first call to this method
// is not a retry it is just an initial failure.
if (!canRetrySameServer(context) && canRetryNextServer(context)) {
context.setServiceInstance(loadBalanceChooser.choose(serviceId));
}
// This method is called regardless of whether we are retrying or making the first
// request.
// Since we do not count the initial request in the retry count we don't reset the
// counter
// until we actually equal the same server count limit. This will allow us to make
// the initial
// request plus the right number of retries.
if (sameServerCount >= lbContext.getRetryHandler().getMaxRetriesOnSameServer()
&& canRetry(context)) {
// reset same server since we are moving to a new server
sameServerCount = 0;
nextServerCount++;
if (!canRetryNextServer(context)) {
context.setExhaustedOnly();
}
}
else {
sameServerCount++;
}
}
根据代码逻辑推理出调用次数=(MaxAutoRetries+1)*(MaxAutoRetriesNextServer+1)-1 按照上面的属性配置重试就会调用5次