一、准备
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集成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接口
最重要的是第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,
这里主要做两件事情: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。
回到HttpAccessor的createRequest,经过上面的流程已经得到了ClientHttpRequestFactory,之后就创建ClientHttpRequest了。
经过这些步骤就创建好了一个ClientHttpRequest。
回到RestTemplate的 doExecute方法
request.execute();执行请求;执行AbstractClientHttpRequest的execute()
执行最终执行InterceptingClientHttpRequest的executeInternal
InterceptingRequestExecution的execute
注意红框内:前文有提到Ribbon的负载均衡拦截器LoadBalancerIntercetor,通过该拦截器采用Ribbon实现负载均衡。LoadBalancerInterceptor:
LoadBalancerClient为RibbonLoadBalancerClient;到这里就调用Ribbon相关的内容了。
Ribbon流程
执行RibbonLoadBalancerClient的Excute
ILoadBalancer loadBalancer = getLoadBalancer(serviceId);得到负载均衡ZoneAwareLoadBalancer,获取服务地址Server server = getServer(loadBalancer);执行请求execute,这里不再详细赘述,后面温故而知新Ribbon再详细介绍。