在使用Spring Cloud开发微服务应用的过程中,不可避免的会遇到微服务间的调用。微服务间的相互调用主要通过两种方式:
-
Feign
-
RestTemplate
Feign的方式本文暂不讨论,而RestTemplate本质上是对OkHttp/HttpClient做了一层封装,通过服务地址向微服务发起HTTP请求没问题,但是又是如何做到,通过服务名进行微服务间的访问的呢?其中的原理,接下来我们会详细阐述。
1.1 启用RestTemplate
@LoadBalanced注解修饰的RestTemplate才能实现服务名的调用,没有修饰的RestTemplate是没有该功能的,只能使用IP、Port访问微服务。
在配置类中注入RestTemplate:
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
// 设置超时
requestFactory.setConnectTimeout(60 * 1000);
requestFactory.setReadTimeout(60 * 1000);
//利用复杂构造器可以实现超时设置,内部实际实现为 HttpClient
RestTemplate restTemplate = new RestTemplate(requestFactory);
return restTemplate;
}
}
然后,即可通过http://SERVICE-NAME/quest-path访问对应名称的微服务。
1.2 @LoadBalanced的作用
@LoadBalanced是Netflix的ribbon中的一个负载均衡的注解,并完成以下工作:
-
从负载均衡器中选一个对应的服务实例,所有的服务名实例都放在负载均衡器中的serverlist中;
-
从挑选的实例中去请求内容;
-
由服务名转为真正使用的ip地址;
1.3 RestTemplate使用服务名访问服务的流程
通过Debug跟踪请求,我们画出了RestTemplate通过服务名访问微服务的流程:
通过源码跟踪可知,restTemplate能通过服务名获取到具体的服务,是由LoadBalancerInterceptor这个拦截器实现的,而具体的工作是由RibbonLoadBalancerClient来完成的。
RibbonLoadBalancerClient将服务名通过负载均衡策略转为了实际的ip和端口后再apply给restTemplate。
参考链接:https://blog.csdn.net/ly279481968/article/details/107789374