一、在配置中加入

<dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId>
</dependency>

二、初始化流程分析

1.构建LoadBalancedRetryFactory,在RibbonAutoConfiguration配置类中。

2.在LoadBalancerAutoConfiguration中构建LoadBalancerRequestFactory负载均衡请求工厂, 以及RetryLoadBalancerInterceptor,并设置在RestTemplate中。

三、调用流程分析

1.还是进入RestTemplate.execute方法,

这里的request还是 InterceptingClientHttpRequest

2.进入拦截器调用,这里的拦截器为 RetryLoadBalancerInterceptor

3.RetryTemplate的interrupt方法, 这里先创建一个重试策略,就是判断当前是否可重试。

package org.springframework.cloud.client.loadbalancer;/*** @author Ryan Baxter* @author Will Tran* @author Gang Li*/
public class RetryLoadBalancerInterceptor implements ClientHttpRequestInterceptor {@Overridepublic ClientHttpResponse intercept(final HttpRequest request, final byte[] body,final ClientHttpRequestExecution execution) throws IOException {final URI originalUri = request.getURI();final String serviceName = originalUri.getHost();Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);final LoadBalancedRetryPolicy retryPolicy = lbRetryFactory.createRetryPolicy(serviceName,loadBalancer);RetryTemplate template = createRetryTemplate(serviceName, request, retryPolicy);return template.execute(context -> {ServiceInstance serviceInstance = null;if (context instanceof LoadBalancedRetryContext) {LoadBalancedRetryContext lbContext = (LoadBalancedRetryContext) context;serviceInstance = lbContext.getServiceInstance();}if (serviceInstance == null) {serviceInstance = loadBalancer.choose(serviceName);}ClientHttpResponse response = RetryLoadBalancerInterceptor.this.loadBalancer.execute(serviceName, serviceInstance,requestFactory.createRequest(request, body, execution));int statusCode = response.getRawStatusCode();if (retryPolicy != null && retryPolicy.retryableStatusCode(statusCode)) {byte[] bodyCopy = StreamUtils.copyToByteArray(response.getBody());response.close();throw new ClientHttpResponseStatusCodeException(serviceName, response, bodyCopy);}return response;}, new LoadBalancedRecoveryCallback<ClientHttpResponse, ClientHttpResponse>() {//This is a special case, where both parameters to LoadBalancedRecoveryCallback are//the same.  In most cases they would be different.@Overrideprotected ClientHttpResponse createResponse(ClientHttpResponse response, URI uri) {return response;}});}

4.首先创建RetryTemplate,这里面主要绑定InterceptorRetryPolicy拦截器重试策略。

5.拦截器重试策略包含了RibbonLoadBalacedRetryPolicy和一个服务实例选择器。RibbonLoadBalancerClient.

6.接着真正执行RetryTemplate.execute方法。一个重试回调,一个恢复回调。

@Override
public final <T, E extends Throwable> T execute(RetryCallback<T, E> retryCallback,RecoveryCallback<T> recoveryCallback) throws E {return doExecute(retryCallback, recoveryCallback, null);
}

7.RetryTemplate的doExecute方法,首先判断是否可重试,可以就调用retryCallback.doWithRetry(context),

org.springframework.retry.support.RetryTemplateprotected <T, E extends Throwable> T doExecute(RetryCallback<T, E> retryCallback,RecoveryCallback<T> recoveryCallback, RetryState state)throws E, ExhaustedRetryException {RetryPolicy retryPolicy = this.retryPolicy;BackOffPolicy backOffPolicy = this.backOffPolicy;// Allow the retry policy to initialise itself...RetryContext context = open(retryPolicy, state);RetrySynchronizationManager.register(context);Throwable lastException = null;boolean exhausted = false;try {// Give clients a chance to enhance the context...boolean running = doOpenInterceptors(retryCallback, context);while (canRetry(retryPolicy, context) && !context.isExhaustedOnly()) {try {lastException = null;return retryCallback.doWithRetry(context);}catch (Throwable e) {lastException = e;try {registerThrowable(retryPolicy, state, context, e);}catch (Exception ex) {throw new TerminatedRetryException("Could not register throwable",ex);}finally {doOnErrorInterceptors(retryCallback, context, e);}if (canRetry(retryPolicy, context) && !context.isExhaustedOnly()) {try {backOffPolicy.backOff(backOffContext);}catch (BackOffInterruptedException ex) {throw ex;}}if (this.logger.isDebugEnabled()) {this.logger.debug("Checking for rethrow: count=" + context.getRetryCount());}if (shouldRethrow(retryPolicy, context, state)) {if (this.logger.isDebugEnabled()) {this.logger.debug("Rethrow in retry for policy: count="+ context.getRetryCount());}throw RetryTemplate.<E>wrapIfNecessary(e);}}}exhausted = true;return handleRetryExhausted(recoveryCallback, context, state);}catch (Throwable e) {throw RetryTemplate.<E>wrapIfNecessary(e);}finally {close(retryPolicy, context, state, lastException == null || exhausted);doCloseInterceptors(retryCallback, context, lastException);RetrySynchronizationManager.clear();}}

8.这里首先为当前请求创建RetryContext,实现类为LoadBalancedRetryContext

9.判断是否可以重试接口,判断重试次数是否为0。

10.接着调用重试函数,又回到RetryLoadBalancerInterceptor。

11.这里的LoadBalancer为RibbonLoadBalanceClient,并且requestFactory.createRequest为之前未重试时普通的HTTP请求类。

ClientHttpResponse response = RetryLoadBalancerInterceptor.this.loadBalancer.execute(serviceName, serviceInstance,requestFactory.createRequest(request, body, execution));

12.LoadBalancerRequestFactory.createRequest又跳到InterceptingRequestExecution这个责任链执行器中。

13.由于这种普通的REQUEST,没有拦截器,直接调用HTTP请求对象替换实例URL中为真实服务实例域名,然后执行HTTP请求。

14.请求接口超时,被RetryTemplate.doExecute方法捕获异常,然后继续获取下一个实例重试。

这里对retryCnt加1.

下面重新选择一个实例,进行设置到context

接着又判断是否可重试。

然后尝试下一个节点,重新调用retryCallback函数。

重新请求成功。

拦截器执行完毕,返回成功。注意这个重试拦截器没有调用execution.interrupt,所以不会再执行责任链的下一个HANDLER.

最后处理结果,进行数据转换,返回数据。

返回结果完毕。

springcloud ribbon retryTemplate操作流程分析相关推荐

  1. 深入分析Ribbon源码分析

    本文来分析下Ribbon源码 文章目录 Ribbon源码分析 负载均衡器 AbstractLoadBalancer BaseLoadBalancer DynamicServerListLoadBala ...

  2. Java微服务组件Spring cloud ribbon源码分析

    微服务组件Spring Cloud Ribbon源码分析_哔哩哔哩_bilibili Ribbon源码分析 | ProcessOn免费在线作图,在线流程图,在线思维导图 | 1.什么是ribbon? ...

  3. SpringCloud详解原理分析

    目录 一.微服务优缺点 1.优点 2.缺点 3.微服务技术栈有哪些 二.Spring Cloud 1.核心组件 2.SpringCloud 和 SpringBoot 关系 3.Dubbo 和 Spri ...

  4. springcloud ribbon @LoadBalance负载均衡源码流程分析

    一.编写示例 1.服务端 pom.xml <properties><java.version>1.8</java.version><spring-cloud. ...

  5. SpringCloud源码:Ribbon负载均衡分析

    本文主要分析 SpringCloud 中 Ribbon 负载均衡流程和原理. SpringCloud版本为:Edgware.RELEASE. 一.时序图 和以前一样,先把图贴出来,直观一点: 二.源码 ...

  6. SpringCloud ribbon源码

    1. 基本使用 server.port=8080spring.application.name=ribbon-clientxxx-server.ribbon.listOfServers=localho ...

  7. Zuul ribbon 重试失效分析

    Zuul ribbon 重试机制 问题描述: Zuul转发POST请求接口异常,read timeout,没有进行重试,期望进行重试! 配置参数模拟 spring.cloud.loadbalancer ...

  8. SpringCloud Ribbon(一)之自定义负载均衡器ILoadBalancer

    一.Ribbon负载均衡 一个服务对应一个LoadBalancer,一个LoadBalancer只有一个Rule,LoadBalancer记录服务的注册地址,提供更新服务的注册地址,Rule提供从服务 ...

  9. SpringCloud Ribbon(二)之自定义负载均衡策略IRule

    一.Ribbon负载均衡策略 一个服务对应一个LoadBalancer,一个LoadBalancer只有一个Rule,LoadBalancer记录服务的注册地址,Rule提供从服务的注册地址中找出一个 ...

最新文章

  1. java redis 主从 哨兵_Redis主从复制与哨兵机制
  2. python将数字转变为中文读法-Python实现把数字转换成中文
  3. hdu 1016 Prime Ring Problem(DFS)
  4. Android高通平台下编译时能生成(拷贝)预编译的so到system的lib目录
  5. 利用系统提供的崩溃日志解Native层Bug
  6. 【MFC】MFC开发之前言
  7. Jdk1.8新特性(二)——lambda表达式(参数列表)-{}和函数式接口@FunctionalInterface
  8. java输入流的控制_Java-Android-IO流-控制台输入输出
  9. 【C语言简单说】八:分支结构之if(1)
  10. oracle display set,Check if the DISPLAY variable is set
  11. shell脚本之从1加到100之和的思路
  12. android vrs技术,VRS技术分析研究及应用
  13. clickhouse创建外部字典表
  14. libtorrent源码分析(三)BT下载相关知识总结
  15. 网站域名被墙(被封锁、被屏蔽、被和谐)后最好的解决方法
  16. Mysql-binlog日志分析
  17. XMLHttpRequest对象的readyState与status
  18. 华为云CDN是怎么为你的下载加速保驾护航
  19. 字符串及有效长度(字节数)计算
  20. 怎样搜索计算机文档,怎么样快速搜索电脑文件 Windows系统秒搜电脑文件

热门文章

  1. 跨境电商未来应该怎么走?
  2. 上下班同行有利于婚姻美满?
  3. sap可配置BOM的主要流程
  4. 下沉市场惊现出行小巨头 松果共享电单车日订单破300w
  5. excel如何匹配同名数据_Excel如何查找名字重复的数据
  6. jdbc不能识别别名_Spark基础:读写JDBC
  7. antv图例出现分页_带图例、文本的饼图
  8. php中删除评论怎么做的,php实现评论回复删除功能
  9. kali linux切换更新源_使用Xshell链接Linux、kali更换更新源及kali安装软件
  10. python添加、修改、删除、访问类对象属性的2种方法