咱们在前面两篇文章分析了Spring Cloud Eureka 注册中心和客户端的源码,在注册中心会有不少同应用名的实例组成集群供客户端调用,这时咱们就须要负载策略来实现如何请求服务.这时咱们就会用到Spring Cloud Ribbon,它是一个服务请求方应用内嵌的一个组件,并非一个服务,也就是说Eureka客户端都集成了Ribbon,在这里不用额外的导入依赖,用法咱们在Ribbon负载均衡---SpringCloud(三)有过介绍,那么如今咱们来分析一下源码,看究竟是怎么实现的;html
咱们利用restTemplate执行一个请求,最后都会经过org.springframework.web.client.RestTemplate#doExecute方法,主要内容以下:web
try { //利用拦截器建立请求 ClientHttpRequest request = createRequest(url, method); if (requestCallback != null) { requestCallback.doWithRequest(request); } //执行请求,负载的功能在这里面实现 response = request.execute(); handleResponse(url, method, response); if (responseExtractor != null) { return responseExtractor.extractData(response); } else { return null; } }
在前面的使用过程当中,咱们知道Ribbon负载均衡主要依赖于RestTemplate实现的,但RestTemplate其实并非Ribbon的组件,咱们看其所在的包可知,该组件在spring-web包下,也就是说RestTemplate只是被Ribbon利用,用于访问外部服务的一个方法,真正实现负载均衡的是咱们加上其上面的注解@LoadBalanced;spring
若是你读了以前分析Spring Cloud Eureka源码分析,相信对***AutoConfiguration很熟悉了吧,延续以前的一向做风,Spring Cloud Ribbon一样也有一个 RibbonAutoConfiguration,先来分析其实例化条件:app
@Configuration @ConditionalOnClass({ IClient.class, RestTemplate.class, AsyncRestTemplate.class, Ribbon.class}) @RibbonClients @AutoConfigureAfter(name = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration") @AutoConfigureBefore({LoadBalancerAutoConfiguration.class, AsyncLoadBalancerAutoConfiguration.class}) @EnableConfigurationProperties(RibbonEagerLoadProperties.class) public class RibbonAutoConfiguration { ....省略内部代码... }
这个应该不用介绍了吧,不过也说一句,主要使得该类被Spring感知到,与@EnableAutoConfiguration配合使用的,若是入口类没有@EnableAutoConfiguration,则@Configuration不会生效;负载均衡
注解@ConditionalOnClass代表了实例化的条件,当上下文中存在所示的几个类的时候;这几个类是干啥的呢?咱们看一下;异步
/** * A client that can execute a single request. * * @author awang * */ public interface IClient<S extends ClientRequest, T extends IResponse> { /** * Execute the request and return the response. It is expected that there is no retry and all exceptions * are thrown directly. */ public T execute(S request, IClientConfig requestConfig) throws Exception; }
看该类注释能够知道,用于访问服务提供方的一个简单调用方法, 没有重试机制,遇到异常则直接抛出,他是一个接口(interface), 也就是说在这里定义了基础的执行请求的方法,如有在执行请求有其余的操做,由其子类实现 工具
由上图实现接口的子类类名也能够看出;源码分析
RestTemplate相信你们确定或多或少的接触过,或者使用过相似的工具类;她主要用来创建HTTP链接,访问外部服务的同步模板工具,咱们根据该类的Note也可知,ui
* <p><strong>Note:</strong> by default the RestTemplate relies on standard JDK * facilities to establish HTTP connections. You can switch to use a different * HTTP library such as Apache HttpComponents, Netty, and OkHttp through the * {@link #setRequestFactory} property.
这里还介绍了其余的相似工具包,你们在项目中也能够应用,看来源码也不不是只介绍关于本身的,也能学到相关其余的东西;url
RestTemplate提供了六种HTTP方法,Put,Post,Delete,Get,Options,Head,其中区别我就不介绍了,你们能够点击或者自由搜索;总之,RestTemplate提供了不少咱们经常使用的模板方法,很灵活,详细你们打开这个类自由查看吧;
与RestTemplate用法相同,与之不一样的是AsyncRestTemplate用于异步调用,这里给你们找了个Demo,自由查看;
/** * A class that can be used to create {@link com.netflix.ribbon.http.HttpResourceGroup}, {@link com.netflix.ribbon.http.HttpResourceGroup.Builder}, * and dynamic proxy of service interfaces. It delegates to a default {@link com.netflix.ribbon.RibbonResourceFactory} to do the work. * For better configurability or in DI enabled application, it is recommended to use {@link com.netflix.ribbon.RibbonResourceFactory} directly. * */
用于自定义配置,细粒度的;
@Configuration @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE }) @Documented @Import(RibbonClientConfigurationRegistrar.class) public @interface RibbonClients { RibbonClient[] value() default {}; Class<?>[] defaultConfiguration() default {}; }
咱们知道,负载均衡的策略有轮询,随机,权重等等...而Ribbon默认的是轮询,若是咱们要指定不一样的策略,就须要在项目入口类使用这个注解导入配置;而一般咱们的服务调用方会调用不少个服务集群,而调用每一个服务的时候负载策略都不同,所以该注解内部又提供了@RibbonClient注解;
用法:@RibbonClient用于注解在项目入口类上,name为服务提供方,value指定自定义负载策略;
@RibbonClients用于整合多个@RibbonClient注解;defaultConfiguration为默认的负载策略;
具体事例咱们以后再提供;//TODO
说明该配置类实例化在注解中配置类以后,这也能够理解,EurekaClientAutoConfiguration是Eureka客户端的配置,而RibbonAutoConfiguration是客户端的一个组件的配置,确定先有客户端,若是须要,才会有Ribbon的配置;
说明该配置类实例化在注解中配置类以前;注解中类作了什么,咱们接下来展开;
负载均衡同步请求自动配置类
用于指定是否支持部分调用服务RibbonClientde 预加载;
在使用Ribbon的时候,常常会遇到一种状况就是第一次执行请求超时,这是因为调用服务的RibbonClient是懒加载的,在第一次请求的时候加载这样就使得第一次请求的时间会很长,容易超过咱们设定的响应超时时间,从而致使响应超时;经过此项配置能够避免这种状况发生;
在这里经过@EnableConfigurationProperties开启了这个配置类经过外部配置文件的属性配置实例化bean的功能,使得该类能够经过@ConfigurationProperties注解指定配置属性在配置文件中的前缀,并将其值注入到成员变量,实例化成bean;
待续...