SpringCloud(Netflix)- 技术专题 - 自定义配置 Ribbon

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

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

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

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

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

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

Eureka 发现组件上目前注册的微服务如下,看到我们的服务提供者是"microservice-provider-user"。
现在既然要自定义负载均衡的方式,那么我们便需要看一看负载均衡的方式都有哪些,我们先按 Ctrl 键再用鼠标放到 configuration 上点击进入该类。
我们可以看到如下图所示的内容,在注释中明确告诉我们使用的是 RibbonClientConfiguration,我们还是 Ctrl 并单击进入该类。


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

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

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

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

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

接下来我们再启动两个名为 microservice-provider-user2 的微服务,这样做是为了更好的看清楚 ribbon 的负载均衡策略是不是按照服务注册名来区分的。如下图所示,我们改端口号为 7902,名称为 microservice-provider-user,改完后我们到启动类启动该微服务。(同理,我们修改端口为 7903,name 依然叫 microservice-provider-user2,再起一个)
起完之后,我们再来看一下 Eureka 主页,如下图所示,可以看到,服务名为 microservice-provider-user 的微服务有两个,名为 microservice-provider-user2 的微服务也有两个。
为了能够更方便的看出不同策略的负载均衡的效果,我们在 movie 微服务中添加了些代码,方便我们测试,如下图所示。
下面我们重启 movie 微服务,然后到地址栏输入:http://localhost:8010/test 并连续刷新多次。

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

要解决这个问题,我们只需要将 IClientConfig config 注释掉,把 ribbonRule 方法中的参数去掉。
然后我们重新启动 movie 服务,然后访问 http://localhost:8010/test,多次刷新,然后我们来看结果,如下图所示,可以看到 user 和 user2 都成随机的了。说明这时 TestConfiguratioin 已经作用在 user 和 user2 两个上面了(虽然我们只配置了一个 user 并没有配置 user2)。所以这样做是不合适的。
要实在想把 TestConfiguratioin 放到 com.itmuch.cloud 及其子目录下,也是可以的。首先我们新建一个注解类如下图所示:

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

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

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

评论