首页 > Java > java教程 > 详细讲解springcloud的组件之RestTemplate集成的Ribbbon

详细讲解springcloud的组件之RestTemplate集成的Ribbbon

php是最好的语言
发布: 2018-08-02 14:28:02
原创
2925 人浏览过

本文讲的是springcloud是如何集成ribbon的,不同的springcloud的组件(feign,zuul,RestTemplate)集成ribbon有所不同,这篇文章先来看看RestTemplate。

RestTemplate的类图如下

1.png

  • HttpAccessor主要根据ClientHttpRequestFactory创建ClientHttpRequest

  • InterceptingHttpAccessor扩展了HttpAccessor,创建拦截的InterceptingClientHttpRequest,这里会设置拦截器ClientHttpRequestInterceptor,这是集成ribbon的核心,当RestTemplate发起http请求调用的时候,会先经过拦截器,然后才真正发起http请求。

拦截器ClientHttpRequestInterceptor是如何被设置的呢?在LoadBalancerAutoConfiguration类中,有如下代码:

1

2

3

@LoadBalanced

@Autowired(required = false)

private List<RestTemplate> restTemplates = Collections.emptyList();

登录后复制

只要加入注解@LoadBalancedRestTemplate会被注入,在没有引入spring retry组件的时候,加载如下配置:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

@Configuration

@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")

static class LoadBalancerInterceptorConfig {

    @Bean

    public LoadBalancerInterceptor ribbonInterceptor(

        LoadBalancerClient loadBalancerClient,

        LoadBalancerRequestFactory requestFactory) {

        return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);

    }

 

    @Bean

    @ConditionalOnMissingBean

    public RestTemplateCustomizer restTemplateCustomizer(

        final LoadBalancerInterceptor loadBalancerInterceptor) {

        return new RestTemplateCustomizer() {

            @Override

            public void customize(RestTemplate restTemplate) {

                List<ClientHttpRequestInterceptor> list = new ArrayList<>(

                    restTemplate.getInterceptors());

                list.add(loadBalancerInterceptor);

                restTemplate.setInterceptors(list);

            }

        };

    }

}

登录后复制

这样RestTemplate就被设置了LoadBalancerInterceptor,下面来看看整个调用过程

1.png

整个过程有点复杂,核心就是经过拦截器LoadBalancerInterceptor,通过RibbonLoadBalancerClient发起负载均衡调用。RibbonLoadBalancerClientI组合了LoadBalancer,所以具备了负载均衡的能力,也就是我们在上一篇文章解读的ribbon原理。

图中我们没有画出真正发起http请求的过程,其默认是由SimpleClientHttpRequestFactory创建,ClientHttpRequestFactory的类图如下:

1.png

从调用时序图上我们看到,开始我们调用的是InterceptingClientHttpRequestFactory来获取InterceptingClientHttpRequest,它们通过组合的方式集成了ClientHttpRequestFactory和拦截器,InterceptingClientHttpRequest发起调用的时候委托了其内部类InterceptingRequestExecution去处理,核心逻辑:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

@Override

public ClientHttpResponse execute(HttpRequest request, byte[] body) throws IOException {

    if (this.iterator.hasNext()) {

        ClientHttpRequestInterceptor nextInterceptor = this.iterator.next();

        return nextInterceptor.intercept(request, body, this);

    }else {

        ClientHttpRequest delegate = requestFactory.createRequest(request.getURI(), request.getMethod());

        for (Map.Entry<String, List<String>> entry : request.getHeaders().entrySet()) {

            List<String> values = entry.getValue();

            for (String value : values) {

                delegate.getHeaders().add(entry.getKey(), value);

            }

        }

        if (body.length > 0) {

            StreamUtils.copy(body, delegate.getBody());

        }

        return delegate.execute();

    }

}

登录后复制

首先会先取出拦截器集合的第一个执行,当拦截器执行完成后,会回调回来,执行else的代码,真正发起http请求,主要有两种方式实现ClientHttpRequestFactory接口:

  • 一种是SimpleClientHttpRequestFactory,使用J2SE提供的方式(既java.net包提供的方式)创建底层的Http请求连接

  • 一种方式是使用HttpComponentsClientHttpRequestFactory方式,底层使用HttpClient访问远程的Http服务,使用HttpClient可以配置连接池和证书等信息。

RestTemplate默认是使用SimpleClientHttpRequestFactory,内部是调用jdk的HttpConnection,默认超时为-1,可以这样设置超时时间:

1

2

3

4

5

6

7

8

@Bean

@LoadBalanced

public RestTemplate restTemplate() {

    SimpleClientHttpRequestFactory factory  = new SimpleClientHttpRequestFactory();

    factory.setConnectTimeout(1000 * 2);//连接超时时间

    factory.setReadTimeout(1000 * 1);//读超时时间

    return new RestTemplate(factory);

}

登录后复制

使用HttpComponentsClientHttpRequestFactory方式可以使用连接池(推荐) ,还可以设置重试策略(具体没有研究过)

如果想开启重试机制,我们可以引入spring的retry组件

1

2

3

4

5

<dependency>

    <groupId>org.springframework.retry</groupId>

    <artifactId>spring-retry</artifactId>

    <version>版本号</version>

</dependency>

登录后复制

这样springcloud-ribbon就会加重如下配置:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

@Configuration

@ConditionalOnClass(RetryTemplate.class)

public static class RetryAutoConfiguration {

    @Bean

    public RetryTemplate retryTemplate() {

        RetryTemplate template =  new RetryTemplate();

        template.setThrowLastExceptionOnExhausted(true);

        return template;

    }

 

    @Bean

    @ConditionalOnMissingBean

    public LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory() {

        return new LoadBalancedRetryPolicyFactory.NeverRetryFactory();

    }

}

 

@Configuration

@ConditionalOnClass(RetryTemplate.class)

public static class RetryInterceptorAutoConfiguration {

    @Bean

    @ConditionalOnMissingBean

    public RetryLoadBalancerInterceptor ribbonInterceptor(

        LoadBalancerClient loadBalancerClient, LoadBalancerRetryProperties properties,

        LoadBalancedRetryPolicyFactory lbRetryPolicyFactory,

        LoadBalancerRequestFactory requestFactory) {

        return new RetryLoadBalancerInterceptor(loadBalancerClient, properties,

                                                lbRetryPolicyFactory, requestFactory);

    }

 

    @Bean

    @ConditionalOnMissingBean

    public RestTemplateCustomizer restTemplateCustomizer(

        final RetryLoadBalancerInterceptor loadBalancerInterceptor) {

        return new RestTemplateCustomizer() {

            @Override

            public void customize(RestTemplate restTemplate) {

                List<ClientHttpRequestInterceptor> list = new ArrayList<>(

                    restTemplate.getInterceptors());

                list.add(loadBalancerInterceptor);

                restTemplate.setInterceptors(list);

            }

        };

    }

}

登录后复制

1

2

3

4

5

6

@Bean

@ConditionalOnClass(name = "org.springframework.retry.support.RetryTemplate")

@ConditionalOnMissingBean

    public LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory(SpringClientFactory clientFactory) {

    return new RibbonLoadBalancedRetryPolicyFactory(clientFactory);

}

登录后复制

拦截器替换成RetryLoadBalancerInterceptor了,这里集成了retry组件retryTemplate。重试策略由RetryHandler接口来配置,默认实现类DefaultLoadBalancerRetryHandler,如下为默认的配置参数

1

2

3

4

5

6

7

8

#最大的重试次数

ribbon.MaxAutoRetries=0

#最大重试server的个数

ribbon.MaxAutoRetriesNextServer=1

#是否开启任何异常都重试(默认在get请求下会重试,其他情况不会重试,除非设置为true)

ribbon.OkToRetryOnAllOperations=false

#指定重试的http状态码

ribbon.retryableStatusCodes=500,501

登录后复制

以上是对全局生效,如果加上xxx.ribbon.MaxAutoRetries=1这样只会对某个ribbon客户端生效。MaxAutoRetries和MaxAutoRetriesNextServer是配合使用的,最大重试次数是针对每一个server的,如果设置MaxAutoRetries=1,MaxAutoRetriesNextServer=1这样触发最大重试次数就是4次。

相关文章:

Java 实例 - 数组转集合

以上是详细讲解springcloud的组件之RestTemplate集成的Ribbbon的详细内容。更多信息请关注PHP中文网其他相关文章!

相关标签:
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
java可以做为web的后端吗?
来自于 1970-01-01 08:00:00
0
0
0
安装JAVA
来自于 1970-01-01 08:00:00
0
0
0
无法安装java
来自于 1970-01-01 08:00:00
0
0
0
java - php调取webservice的map类型,如果封装?
来自于 1970-01-01 08:00:00
0
0
0
这个是Java语言的吗
来自于 1970-01-01 08:00:00
0
0
0
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板