一、准备

Spring Boot :2.0.8.RELEASE
Spring Cloud : Finchley.SR2
Nacos : 0.8.0
建立两个工程;Nacos作为注册中心。
工程1:provider,只简单的提供一个接口provider

@SpringBootApplication
@EnableDiscoveryClient
@RestController
@Slf4j
public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
    @GetMapping("provider")
    public String provider(){
        log.info("..................................");
        return "i am provider";
    }
}

工程2:consume,只简单的采用RestTemplate进行调用provider

@SpringBootApplication
@Slf4j
@EnableDiscoveryClient
@RestController
public class ConsumeApplication {
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
    @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);
    }

}

二、RestTemplate

2.1 RestTemplate类图

温故知新(一)—— RestTemplate
RestTemplate集成InterceptingHttpAccessor、实现RestOption;InterceptingHttpAccessor继承HttpAccess;

2.2执行流程

用postman发起请求http://locahost:7777/test;即调用consume工程的test接口,之后通过RestTemplate向provider服务发起请求

    @GetMapping("test")
    public String getContent(){
        log.info("发起请求");
        return restTemplate.getForObject("http://provider/provider",String.class);
    }

之后会调用RestTemplate的doExecute接口
温故知新(一)—— RestTemplate
最重要的是第683行调用父类的createRequest方法获取ClientHttpRequest,HttpAccessor中的createRequest

protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException {
		ClientHttpRequest request = getRequestFactory().createRequest(url, method);
		if (logger.isDebugEnabled()) {
			logger.debug("Created " + method.name() + " request for \"" + url + "\"");
		}
		return request;
	}

getRequestFactory()获取ClientHttpRequestFactory,因为InterceptingHttpAccessor重写了getRequestFactory,
温故知新(一)—— RestTemplate
这里主要做两件事情:1.判断是否有拦截器ClientHttpRequestInterceptor,如果有那么就生成InterceptingClientHttpRequestFactory;2.如果没有那么获取默认的ClientHttpRequestFactory,默认为SimpleClientHttpRequestFactory。

注意下面这句

factory = new InterceptingClientHttpRequestFactory(super.getRequestFactory(), interceptors);

InterceptingClientHttpRequestFactory只是个包装者,super.getRequestFactory()真正的ClientHttpRequestFactory还是SimpleClientHttpRequestFactory。

因为SpringCloud默认集成了Ribbon,默认注入了Ribbon的RibbonLoadBalancerClient,代码在LoadBalancerAutoConfiguration,注意这个注解**@ConditionalOnMissingClass(“org.springframework.retry.support.RetryTemplate”)** ,后面我们再介绍RetryTemplate。
温故知新(一)—— RestTemplate
回到HttpAccessor的createRequest,经过上面的流程已经得到了ClientHttpRequestFactory,之后就创建ClientHttpRequest了。
经过这些步骤就创建好了一个ClientHttpRequest。
回到RestTemplate的 doExecute方法
温故知新(一)—— RestTemplate
request.execute();执行请求;执行AbstractClientHttpRequest的execute()
温故知新(一)—— RestTemplate
执行最终执行InterceptingClientHttpRequest的executeInternal
温故知新(一)—— RestTemplate
InterceptingRequestExecution的execute
温故知新(一)—— RestTemplate
注意红框内:前文有提到Ribbon的负载均衡拦截器LoadBalancerIntercetor,通过该拦截器采用Ribbon实现负载均衡。LoadBalancerInterceptor:
温故知新(一)—— RestTemplate
LoadBalancerClient为RibbonLoadBalancerClient;到这里就调用Ribbon相关的内容了。

Ribbon流程

执行RibbonLoadBalancerClient的Excute
温故知新(一)—— RestTemplate
ILoadBalancer loadBalancer = getLoadBalancer(serviceId);得到负载均衡ZoneAwareLoadBalancer,获取服务地址Server server = getServer(loadBalancer);执行请求execute,这里不再详细赘述,后面温故而知新Ribbon再详细介绍。

源码地址

相关文章: