Ribbon使用
在上一章中,虽然服务之间的调用使用的负载均衡方式是 Ribbon,但是表面并没有涉及包的依赖。其实,在内部是引用了的,为了让读者可以理解负载均衡在客户端的使用,本节会做一个演示。
客户端负载均衡
首先,我们需要知道 Ribbon 的负载均衡是客户端负载均衡。负载均衡主要的功能是缓解网络压力,实现系统的高可用。在系统中,一般分为服务端负载均衡与客户端负载均衡。
关于服务端的负载均衡,主要有两个策略,即硬件负载均衡与软件负载均衡。硬件负载均衡就是在服务器的各个节点上安装用于负载均衡的设备;软件负载均衡一般是在服务端存在软件时可以对请求进行转发,例如常见的 Nginx。
在这一章节,我们使用的 Ribbon 则是客户端负载均衡,请求列表维护在客户端,然后通过一定的规则,在列表中选择请求进行访问,最后达到负载均衡的效果。
为了更好地说明服务端与客户端的区别,将通过图11.1、图11.2进行讲解。


使图11.1与图11.2进行对比,在服务端负载均衡时,存在代理对服务端的列表进行选择,并返回一个请求给客户端;但在客户端负载均衡时,则是把列表全部给客户端,这个代理相当于在客户端,均衡的操作逻辑由客户端完成。不过,在这一个章节中,负载均衡就由 Ribbon 自己进行。
Ribbon实例
这里进行的实例演示,不再重新搭建环境,直接在第 10 章的基础上进行,这里会向读者清晰说明,可以迅速实现效果。
首先,我们启动一个服务注册中心。在 Ribbon 的演示中,重要的是演示服务提供者都可以被轮询执行到,所以启动服务注册中心就好,不需要使用高可用,增加重现复杂度。下面是 application.properties 的内容。
server.port=8764
eureka.client.service-url.defaultZone=http://localhost:8764/eureka/
eureka.client.register-with-eureka=false
在这段配置内容上,我们可以看到服务注册中心端口是 8764,后面的服务提供者和消费者都使用这个服务注册中心。
然后,我们分别启动两个服务提供者应用。先启动一个应用,然后直接复制,再修改启动端口的方式,作为下一个启动的应用。这个应用将会有两段 application.properties 的配置内容,第一段代码如下所示。
server.port=8091
spring.application.name=helloService
eureka.client.service-url.defaultZone=http://localhost:8764/eureka/
第二段代码如下所示。
server.port=8090
spring.application.name=helloService
eureka.client.service-url.defaultZone=http://localhost:8764/eureka/
根据配置文件,可以知道在注册中心的信息面板上,应该会出现两个应用都是 helloservice 的注册信息。
最后,启动服务消费者应用。下面是服务消费者应用中的 application.properties 的配置内容。
server.port=8070
spring.application.name=consumerService
eureka.client.service-url.defaultZone=http://localhost:8764/eureka/
这段配置说明我们可以通过 8070 端口访问注册中心上注册的应用服务。所以,下面通过多次访问 8070 端口上的服务,观察在控制台上的信息,并观察这里的服务是否通过 Ribbon 完成了负载均衡。
访问链接 http://localhost:8070/consumer 。这个链接的代码如下所示。
package com.cloudtest.eurekaconsumer.controller;
@RestController
public class ConsumerController {
@Autowired
RestTemplate restTemplate;
@GetMapping("/consumer")
public String consumer(){
//第三种方式
sreturn restTemplate.getForEntity("http://HELLOSERVICE/hello",String.class). getBody();
}
}
在这段代码中,我们在第 10 章解释过有关问题,就是通过 “/consumer” 的访问,将请求发送到服务注册中心,访问应用 Helloservice 中的 hello 服务。再看看 “/hello” 的代码,代码如下所示。
@RestController
public class HelloController {
@Autowired
private DiscoveryClient client;
@Autowired
private Registration registration; // 服务注册
private final Logger logger = LoggerFactory.getLogger(HelloController.class);
@GetMapping("/hello")
public String hello(){
ServiceInstance instance = serviceInstance();
String result = "host:port=" + instance.getUri() + ", "
+ "service_id:" + instance.getServiceId();
logger.info(result);
return "hello eureka!";
}
public ServiceInstance serviceInstance() {
//这里的代码,在第10章有,此处省略
}
}
在上面的代码中,根据预期,最终的测试结果,页面上会返回 “hello eureka!”,然后在控制台上输出服务实例的信息。执行结果如图11.3所示。

在页面上,展示了我们的预期效果。然后,我们对这个链接进行两次请求访问,下面观察控制台的信息。展示应用的控制台的日志如下。
2019-01-13 22:02:22.066
INFO16492---[nio-8090-exec-5]c.c.e.controller.HelloController:
host:port=http://DESKTOP-TQ4OD79:8090, service_id:HELLOSERVICE
在上面的日志中,我们可以发现在 8090 端口上返回客户端实例信息。继续测试,展示应用的控制台的日志。
2019-01-13 22:02:23.697
INFO1760--[nio-8091-exec-8]c.c.e.controller.HelloController:
host:port=http://DESKTOP-TQ4OD79:8090, service_id:HELLOSERVICE
在上面的日志中,可以发现在 8091 端口上返回了客户端实例信息。
Ribbon用法总结
回忆一下,在讲解10.2节的 Eureka 服务消费时使用过 RestTemplate,但具体原因没有说明,这里我们需要了解一下,做到对程序 “知其然” 也 “知其所以然”。
Ribbon 通过 RestTemplate 来实现客户端负载均衡。在客户端的负载均衡时,不需要单独引用关于 Ribbon 的依赖,因为在引用 Eureka Client 时,依赖已经被引用了。找到 IDEA 关于依赖的引用,可以查找到图11.4所示的依赖。

在 Eureka 上实现服务的负载均衡主要有两个步骤,即引用一个被 @LoadBalanced 注解过的 RestTemplate 对象,然后在程序中使用 RestTemplate 即可。