spring-cloud 学习笔记,第四章,介绍了 Spring-cloud-ribbon 相关内容 ,记录笔记,供个人回顾使用。
RestTemplate 详解
目前理解功能是封装的通过 REST 远程访问经过 eureka 负载均衡的 spring 服务。
对于 HTTP 的 GET,POST,PUT,DELETE 等均有对应实现。
源码分析
@LoadBalanced 注解的作用是标记一个 RestTemplate Bean , 用 LoadBalancerClient 来对它进行配置。
LoadBalancerClient 是 org.springframework.cloud.client.loadbalancer 下的一个接口,它提供了三个方法。
1 | /** |
LoadBalancerAutoConfiguration 是 org.springframework.cloud.client.loadbalancer 包下的,为了实现客户端负载均衡的自动化配置类。
1 |
|
@ConditionalOnClass, 指定类位于 classpath 时,匹配成功
@ConditionalOnBean,当所有依赖的 bean 已经存在于 BeanFactory 容器中时,匹配成功。
@ConditionalOnMissingBean 当前 bean 不存在 BeanFactory 中时,匹配成功。
@EnableConfigurationProperties 开启可以通过 ConfigurationProperties 的注解 bean 来对自动配置文件进行配置
所以 LoadBalancerAutoConfiguration,在 classpath 下有 RestTemplate.class 和 BeanFactory 存在 LoadBalancerClient 时,自动启用。同时,支持通过 LoadBalancerRetryProperties 类来对配置内容进行修改。
继续看源码,下面的配置是当缺少 RetryTemplate.class 时,进行配置的一些内容。
1 | /** |
下面,查看 LoadBalancerInterceptor 拦截器如何将一个普通的 RestTemplate 变成客户端负载均衡的
1 |
|
之前也提到过,RestTemplate 的 host 为服务名,所以通过 URI 获取的 host 就是 service 的服务名。负载均衡,通过 serviceName 选择实例,并发起请求。
接下来,我们查看一下 ribbo 对于 LoadBalancerClient 的具体实现。
1 | public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) |
新加入了一个 hint 来和 execute(serviceId, ServiceInstance, request) 区分,默认 hint 传递的是 null。
开始会通过 getServer 来获取 server。代码如下,这里通过 com.netflix.loadbalancer 的 ILoadBalancer 来选择 server
1 | protected Server getServer(ILoadBalancer loadBalancer, Object hint) { |
ILoadBalancer 接口提供了下列方法
1 | public interface ILoadBalancer { |
通过查看 RibbonClientConfiguration 可以发现,Ribbon 用 ZoneAwareLoadBalancer 来默认实现 ILoadBalancer 来实现负载均衡器。
1 |
|
在通过 ILoadBalancer 来获取到 server 后,将 server 包装成了 RibbonServer , 随后获取了 serviceId 对应的 负载均衡的上下文,记录了状态,再回调 LoadBalancerRequest 的 apply 方法进行处理。
1 |
|
传入 apply 的 ServiceInstance 是对服务实例的抽象定义,在该接口中暴露出了每个服务实例需要的基本信息,例如 serviceId, host, port 等。
1 | public interface ServiceInstance { |
到这里,重新整理一下逻辑。
在 LoadBalancerAutoConfiguration 中,通过 LoadBalancerInterceptor bean 来拦截负载均衡的 RestTemplate 请求,从而达到负载均衡的效果。
LoadBalancerInterceptor 是由 LoadBalancerClient 和 LoadBalancerRequestFactory 两个参数生成。
- LoadBalancerClient 主要功能是执行请求,上文也分析了 excute 方法。
- LoadBalancerRequestFactory 是用来构造 LoadBalancerRequest 请求对象。
现在分析一下 LoadBalancerRequestFactory, 该对象由一个 LoadBalancerClient 对象和一个 1
2
3
4
5
6
7
```java
public LoadBalancerRequestFactory(LoadBalancerClient loadBalancer,
List<LoadBalancerRequestTransformer> transformers) {
this.loadBalancer = loadBalancer;
this.transformers = transformers;
}
LoadBalancerRequestTransformer 的主要功能就是传递负载均衡的 HttpRequest 给指定的 ServiceInstance。
1 | (LoadBalancerRequestTransformer.DEFAULT_ORDER) |
接着看 LoadBalancerRequestFactory,其中核心的方法是 createRequest 方法,目的是生成一个 LoadBalancerRequest 对象。
1 | public LoadBalancerRequest<ClientHttpResponse> createRequest( |
这里通过 ServiceRequestWrapper 来包装 request 和 serviceInstance,来看下 ServiceRequest 方法,构造的时候要传入 LoadBalancerClient 对象,通过调 this.loadBalancer.reconstructURI 来对 URI 进行重构。同时,该对象继承了 HttpRequestWrapper ,最后就可以生成一个 HttpRequest 对象,到这里,就把请求转换为了 HttpRequest。
1 | public class ServiceRequestWrapper extends HttpRequestWrapper { |
这里再调用前面的 LoadBalancerRequestTransformer , 根据 ServiceInstance 的信息,将请求发送到对应的服务实例上。
1 | if (this.transformers != null) { |
到这里,就说明白了 LoadBalancerClient 和 LoadBalancerRequestFactory 在 LoadBalancerInterceptor 下的作用。
继续看 LoadBalancerInterceptor 的 intercept 方法,也就是实际对请求进行拦截的方法。
1 |
|
最后 execute 就用到了 RibbonLoadBalancerClient 下的 execute 方法,具体分析见上文,一直到使用 apply 方法,就调用了 LoadBalancerRequestFactory 的 createRequest 里的方法,这里的具体执行方式,上文也进行过了分析。
1 | return instance -> { |