温故知新(三)—— RetryTemplate与Ribbon重试

开始

环境

Spring Boot :2.0.8.RELEASE
Spring Cloud : Finchley.SR2
Nacos : 0.8.0

在上一篇中只是大致说了RestTemplate如何实现超时设置,当超时时就会直接抛出异常,在微服务时代各个服务之间互相调用难免因为网络波动导致调用失败的情况,这时候是希望能够实现重试了。
把功能稍微改一下
consume工程修改,把ConnectTimeout与ReadTimeout

public class ConsumeApplication {
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        clientHttpRequestFactory.setConnectTimeout(5 * 1000);
        clientHttpRequestFactory.setReadTimeout(5 * 1000);
        return new RestTemplate(clientHttpRequestFactory);
    }
    @Autowired
    RestTemplate restTemplate;
    public static void main(String[] args) {
        SpringApplication.run(ConsumeApplication.class, args);
    }
    @GetMapping("test")
    public String getContent(){
        log.info("发起请求");
        return restTemplate.getForObject("http://provider/provider",String.class);
    }

}

provider工程开启运行多实例
在这里插入图片描述
先运行一个实例,端口号9667,之后修改端口号为9668,同时修改接口,加个20秒的阻塞
在这里插入图片描述
运行如下:
在这里插入图片描述
就可以尝试如何实现重试功能了。

RetryTemplate

需要实现重试功能,那么就需要RetryTemplate,在工程中引入

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

在没有引入RetryTemplate之前,Ribbon只负责实现负载均衡,引入之后那么负载均衡就会使用LoadBalancedRetryFactory和RetryLoadBalancerInterceptor,RibbonAutoConfiguration中如下:

    @Bean
	@ConditionalOnClass(name = "org.springframework.retry.support.RetryTemplate")
	@ConditionalOnMissingBean
	public LoadBalancedRetryFactory loadBalancedRetryPolicyFactory(final SpringClientFactory clientFactory) {
		return new RibbonLoadBalancedRetryFactory(clientFactory);
	}

LoadBalancerAutoConfiguration中:
在这里插入图片描述

RibbonLoadBalancedRetryFactory中主要负责创建重试策略、重试监听等

public class RibbonLoadBalancedRetryFactory implements LoadBalancedRetryFactory {

	private SpringClientFactory clientFactory;

	public RibbonLoadBalancedRetryFactory(SpringClientFactory clientFactory) {
		this.clientFactory = clientFactory;
	}

	@Override
	public LoadBalancedRetryPolicy createRetryPolicy(String service, ServiceInstanceChooser serviceInstanceChooser) {
		RibbonLoadBalancerContext lbContext = this.clientFactory
				.getLoadBalancerContext(service);
		return new RibbonLoadBalancedRetryPolicy(service, lbContext, serviceInstanceChooser, clientFactory.getClientConfig(service));
	}

	@Override
	public RetryListener[] createRetryListeners(String service) {
		return new RetryListener[0];
	}

	@Override
	public BackOffPolicy createBackOffPolicy(String service) {
		return null;
	}
}

RibbonLoadBalancedRetryPolicy主要用来判断是否能够满足重试条件,主要代码如下
在这里插入图片描述
其中canRetry接口用来判断请求类型是否允许重试,默认只允许GET请求能够重试,如果需要所有的请求都能实现重试,那么需要设置OkToRetryOnAllOperations为true(当然不建议这么做)。
canRetryNextServer主要用来判断是否满足调用下一个服务的条件。lbContext.getRetryHandler()是默认的DefaultLoadBalancerRetryHandler,
retrySameServer:默认情况下是0,即重试自身服务的次数为0,
retryNextServer:默认情况下是1,即重试下个服务的次数为1,
retryEnabled:即是否说有请求都重试,默认是false。
在这里插入图片描述
自定义设置可以在yml文件中设置:

ribbon:
	MaxAutoRetries: 1
	MaxAutoRetriesNextServer: 2

到这里发现,Ribbon的ConnectTimeout与ReadTimeout根本没有任何用处,卧槽,是不是很奇怪,哈哈。

在HttpClientRibbonConfiguration中如下:

         @Bean
		@ConditionalOnMissingBean(CloseableHttpClient.class)
		public CloseableHttpClient httpClient(ApacheHttpClientFactory httpClientFactory,
											  HttpClientConnectionManager connectionManager, IClientConfig config) {
			RibbonProperties ribbon = RibbonProperties.from(config);
			Boolean followRedirects = ribbon.isFollowRedirects();
			Integer connectTimeout = ribbon.connectTimeout();
			RequestConfig defaultRequestConfig = RequestConfig.custom()
					.setConnectTimeout(connectTimeout)
					.setRedirectsEnabled(followRedirects).build();
			this.httpClient = httpClientFactory.createBuilder().
					setDefaultRequestConfig(defaultRequestConfig).
					setConnectionManager(connectionManager).build();
			return httpClient;
		}

@ConditionalOnMissingBean(CloseableHttpClient.class)即没有实例化CloseableHttpClient的情况下才执行,在上面new HttpComponentsClientHttpRequestFactory 的时候已经创建了CloseableHttpClient,如下:

/**
	 * Create a new instance of the {@code HttpComponentsClientHttpRequestFactory}
	 * with a default {@link HttpClient}.
	 */
	public HttpComponentsClientHttpRequestFactory() {
		this.httpClient = HttpClients.createSystem();
	}

这里当然就没有用到Ribbon的ConnectTimeout与ReadTimeout了,即使设置也是没得用。

如果想不单独设置HttpComponentsClientHttpRequestFactory,紧密结合Ribbon,那么只要yml文件中设置如下即可
ribbon.http.client.enabled=true或ribbon.restclient.enabled=true都行

这样在RibbonAutoConfiguration中给restTemplate设置RequestFactory
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值