天天看点

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

      上节课我们一起学习了使用Ribbon做为负载均衡的工具,这节我们一起学习如何通过代码自定义配置Ribbon。

       我们还是先从官网文档开始学习,如下图所示,我们可以搞一个测试配置类,来验证是否真的可以通过代码来自定义配置Ribbon,但文档明确给出了警告:即这个测试配置类不能放在@ComponentScan所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,也就是说我们达不到特殊化定制的目的了。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

          那么,哪个类用到了@ComponentScan注解了呢?由于Ribbon是负责客户端负载均衡的,因此我们要配置的自然就是我们的movie微服务了,movie微服务的启动类中有一个@SpringBootApplication注解,我们按Ctrl再点击SpringBootApplication类进入该注解类。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

       SpringBootApplication接口类如下图所示,可以看到在该接口类上有我们所说的@ComponentScan注解,这也就意味着,凡是该启动类所在的包(com.itmuch.cloud)以及该包的子包都将被所有Ribbon客户端所共享。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

         因此,为了让我们所定义的配置类不在@ComponentScan的扫描范围下,我们便需要在包"com.itmuch.cloud"之上来放置,这里我选择了放在com.itmuch.config包下,如下图所示。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

         这里大家可能注意到了,在官方文档中,TestConfiguration类上方有一行注解@RibbonClient,如下图所示。(这里需要说明的是:FooConfiguration.class应该换成我们定义的类TestConfiguration)

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

          我把它放到启动类上了,如下图所示,这样做的目的无非是为了在启动该微服务的时候就能去加载我们的自定义Ribbon配置类,从而使配置生效。(这里有一点需要说明的是,@RibbonClient(name="microservice-provider-user"这个microservice-provider-user不是随便写的,而是注册到Eureka发现组件上的微服务服务端,意思是要对所有工程名为microsevice-provider-user的服务提供者进行负载均衡管理)

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

      Eureka发现组件上目前注册的微服务如下,可以看到我们的服务提供者是"microservice-provider-user"。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

        现在既然要自定义负载均衡的方式,那么我们便需要看一看负载均衡的方式都有哪些,我们先按Ctrl键再用鼠标放到configuration上点击进入该类。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

         我们可以看到如下图所示的内容,在注释中明确告诉我们使用的是RibbonClientConfiguration,我们还是Ctrl并单击进入该类。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

         我们会看到如下图所示的内容,在该类中有所有的自定义的负载均衡策略。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

        我们Ctrl+F搜索"ribbonrule"便可以看到如下图所示的方法。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

         我们就借用一下该方法到我们的TestConfiguration类中,如下图所示。大家应该看到了,我们注入的config类有警告,其实这是不影响运行的,不必理会它。如果大家实在看着别扭,可以参考:http://blog.csdn.net/u012453843/article/details/54906905这篇博客进行处理,就不会报警告了。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

          刚才我们在Eureka服务发现组件上只注册了一个服务提供者(user微服务),为了可以看出来负载均衡的不同效果,我们再起一个名为microservice-provider-user的服务提供者,只是端口需要改下,另外再起两个名为microservice-provider-user的服务提供者,注意端口不能一样。其实要做到这些非常简单,我们只需要修改user微服务的application.yml文件就可以了。我们已经注册的那个user微服务的端口号是7900,那么我们第二个名为microservice-provider-user的微服务的端口便改为7901。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

        改完之后,我们到user微服务的启动类去启动7901端口的user微服务。启动完之后,我们再到Eureka主页看下当前注册的微服务,发现已经有两个名为microservice-provider-user的微服务注册进来了,只是端口不一样而已。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

         接下来我们再启动两个名为microservice-provider-user2的微服务,这样做是为了更好的看清楚ribbon的负载均衡策略是不是按照服务注册名来区分的。如下图所示,我们改端口号为7902,名称为microservice-provider-user,改完后我们到启动类启动该微服务。(同理,我们修改端口为7903,name依然叫microservice-provider-user2,再起一个)

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

        起完之后,我们再来看一下Eureka主页,如下图所示,可以看到,服务名为microservice-provider-user的微服务有两个,名为microservice-provider-user2的微服务也有两个。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

         为了能够更方便的看出不同策略的负载均衡的效果,我们在movie微服务中添加了些代码,方便我们测试,如下图所示。

this.loadBalancerClient.choose("microservice-provider-user");可以随机获取名为microservice-provider-user的一个微服务的实例,并用该实例做相应的事情。      
学习Spring Cloud第八课(通过代码自定义配置Ribbon)

         下面我们重启movie微服务,然后到地址栏输入:http://localhost:8010/test并连续刷新多次。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

           然后我们到movie的控制台下看看负载均衡的调用情况,如下图所示,我们通过观察可以发现,服务一的调用是没有规律的(即端口7900和7901出现的次数没有规律可言,说明是随机策略。而服务二则不同,它出现的非常规律,7903和7902依次出现数量相等,说明这是轮询策略)这也说明了,我们自定义的随机策略起作用了,而且只作用在了名为microservice-provider-user的微服务上,并未影响名为microservice-provider-user2的微服务。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

          既然说TestConfiguration在com.itmuch.cloud下会有问题,那么我们就来试试,先把TestConfiguration放到com.itmuch.cloud.config目录下。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

        我们再运行MicroserviceSimpleConsumerMovieApplication,会出现如下所示错误:

2017-12-02 11:20:32.956  INFO 4872 --- [           main] croserviceSimpleConsumerMovieApplication : No active profile set, falling back to default profiles: default

refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'testConfiguration': Unsatisfied dependency expressed through field 'config'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.netflix.client.config.IClientConfig' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.

        要解决这个问题,我们只需要将IClientConfig config注释掉,把ribbonRule方法中的参数去掉。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

            然后我们重新启动movie服务,然后访问http://localhost:8010/test,多次刷新,然后我们来看结果,如下图所示,可以看到user和user2都成随机的了。说明这时TestConfiguratioin已经作用在user和user2两个上面了(虽然我们只配置了一个user并没有配置user2)。所以这样做是不合适的。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

           要实在想把TestConfiguratioin放到com.itmuch.cloud及其子目录下,也是可以的。首先我们新建一个注解类如下图所示:

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

       接着我们在MicroserviceSimpleConsumerMovieApplication启动类上面加上@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = ExcludeFromComponentScan.class)})如下图所示。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

          下面我还需要在TestConfiguration类上方添加我们刚才写的注解@ExcludeFromComponentScan,如下图所示。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

            好,下面我们来重新启动movie服务,然后多次访问http://localhost:8010/test,运行结果如下图所示,可以看到user是随机的,user2是轮询的,说明把TestConfiguration类放到@ComponentScan扫描包下面也不是不可以,只是需要排除掉它就可以了。

学习Spring Cloud第八课(通过代码自定义配置Ribbon)

继续阅读