本节来为前文编写的电影微服务整合Ribbon。
1.复制项目microservice-consumer-movie,将ArtifactId修改为microservice-consumer-movie-ribbon。
2.为项目引入Ribbon的依赖,Ribbon的依赖如下:
由于前文中已为电影微服务添加了spring-cloud-starter-netflix-eureka-client,该依赖已包含spring-cloud-starter-netflix-ribbon,因此无须再次引入。
3.为RestTemplate添加@LoadBalanced注解。
对比两者可以发现,只需添加注解@LoadBalanced注解,就可为RestTemplate整合Ribbon,使其具备负载均衡的能力。
4.对Controller代码进行修改,如下所示。
由代码可知,我们将请求的地址改成了http://microservice-provider-user/。microservice-provider-user是用户微服务的 虚拟主机名 (virtualhostname),当Ribbon和Eureka配合使用时,会自动将虚拟主机名映射成微服务的网络地址。在新增的log-User Instance()方法中可使用LoadBalancerClient的API更加直观地获取当前选择的用户微服务节点。
测试
1.启动microservice-discovery-eureka。
2.启动2个或更多microservice-provider-user实例。
3.启动microservice-consumer-movie-ribbon。
4.访问 http://localhost:8761 ,结果如图5-2所示。
图5-2 Eureka Server上的微服务列表
5.多次访问 http://localhost:8010/user/1 ,返回如下结果:
同时,两个用户微服务实例都会打印类似如下的日志:
6.多次访问 http://localhost:8010/log-user-instance ,控制台会打印如下日志:
可以看到,此时请求会均匀分布到两个用户微服务节点上,说明已经实现了负载均衡。
●虚拟主机名与虚拟IP非常类似,如果大家接触过HAProxy或Heartbeat,理解虚拟主机名就非常容易了。如果无法理解虚拟主机名,可将其简单理解成为提供者的服务名称,因为在默认情况下,虚拟主机名和服务名称是一致的。当然,也可使用配置属性eureka.instance.virtual-host-name或者eureka.instance.secure-virtual-host-name指定虚拟主机名。
●不能将restTemplate.getForObject(...)与loadBalancerClient.choose(...)写在同一个方法中,两者之间会有冲突——因为此时代码中的restTemplate实际上是一个Ribbon客户端,本身已经包含了“choose”的行为。
虚拟主机名不能包含“_”之类的字符,否则Ribbon在调用时会报异常。相关Issue详见: https://github.com/spring-cloud/spring-cloud-netflix/issues/1582 .