Spring Cloud Ribbon 是一套实现客户端负载均衡的工具。当然也有服务端的负载均衡工具,我们后面再介绍。可以认为 Ribbon 就是一个负载均衡器(Load Balancer)。负载均衡就是将用户的请求平摊的分配到多个服务上,从而达到系统的高可用。
简单来说,Ribbon 的主要功能是提供客户端的软件负载均衡算法,将 Netflix 的中间层服务连接在一起。Ribbon 客户端组件给我们提供了一套很完善的配置项,比如可以配置连接超时、重试等等。
前面文章中,将订单服务注册到 Eureka,然后消费方可以通过 http 请求去获取订单的信息,但是这是最原始的 http 调用,没有任何 Ribbon 的东西在里面,接下来我们要在消费方(即microservice-order-consumer)植入 Ribbon
1.导入Ribbon依赖包
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
Eureka Client 的依赖也需要导入,因为服务注册到了 Eureka,Ribbon 也需要和 Eureka 整合,所以在消费方也导入了 Eureka 依赖。
2.配置application文件:
server.port = 9001
eureka.client.register-with-eureka = false
eureka.client.service-url.defaultZone = http://eureka01:7001/eureka/,http://eureka02:7002/eureka/,http://eureka03:7003/eureka/
消费方这里也分别向eureka01, eureka02和eureka03注册,也作为了一个Eureka Client
3. 在http中植入Ribbon
Ribbon为客户端提供负载均衡服务,之前的 microservice-order-consumer 中是使用 RestTemplate 来发送 http 请求,调用订单服务的,但是没有负载均衡,所以现在我们要让这个 http 调用自带负载均衡。
@Configuration
public class RestTmplateConfig {
/**
* '@LoadBalanced'注解表示使用Ribbon实现客户端负载均衡
* @return RestTemplate
*/
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
在RestTemplate上添加一个 @LoadBalanced
注解即可开启 Ribbon 负载均衡。这样就可以通过微服务的名字从 Eureka 中找到对应的服务并访问了
4. 将IP改成服务名
将接口中的localhost:8001 改成服务提供方在Eureka中注册服务的暴露名称:MICROSERVICE-ORDER
@EnableEurekaClient
@RestController
@RequestMapping("/consumer/order")
public class OrderConsumerController {
// 订单服务提供者模块的 url 前缀
//private static final String ORDER_PROVIDER_URL_PREFIX = "http://localhost:8001";
private static final String ORDER_PROVIDER_URL_PREFIX = "http://MICROSERVICE-ORDER";
@Resource
private RestTemplate restTemplate;
@GetMapping("/get/{id}")
public TOrder getOrder(@PathVariable Long id) {
return restTemplate.getForObject(ORDER_PROVIDER_URL_PREFIX + "/provider/order/get/" + id, TOrder.class);
}
@GetMapping("/get/list")
public List getAll() {
return restTemplate.getForObject(ORDER_PROVIDER_URL_PREFIX + "/provider/order/get/list", List.class);
}
}
注释掉的那部分,是原来的访问方式,订单提供服务是8001端口,现在我们将ip+端口号这种访问方式,改成微服务名称,这个名称就是 Eureka 管理界面显示的注册进去的名称,也即服务提供方的application配置文件中配置的服务名称:
# 服务端口号
server.port = 8001
# 对外暴露的服务名称
spring.application.name = MICROSERVICE-ORDER
启动测试:
分别启动 eureka7001、eureka7002、eureka7003以及订单服务8001,可以看到订单服务已经注册到 Eureka 集群。
然后启动消费服务访问:http://localhost:9001/consumer/order/get/list
初步实现客户端使用Ribbon负载均衡
实现负载均衡,要有多个订单服务提供者,目前我们就一个provider01,端口号 8001 ,参照这个服务,再创建两个子模块,也是订单服务提供者,取名为 provider02和provider03,端口号分别命名为8002和8003
现在的负载均衡架构图
Ribbon 是客户端的负载均衡工具,它在服务的消费方,首先三个订单服务 8001、8002和8003都会注册到 Eureka 集群,Ribbon 会先从 Eureka 集群中查询可用的服务列表,然后根据 Ribbon 提供的负载均衡算法,负载均衡的请求可用的订单服务。
Ribbon 默认的负载均衡算法是轮询,也就是按顺序挨个的调用。我们先来搭建一下整个服务架构,上面提到了,首先要拷贝两个订单服务,端口号分别为 8002 和 8003
三个订单服务配置对比:
#8001
# 服务端口号
server.port = 8001
# 数据库配置
spring.datasource.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/demo?
# 人性化显示出服务的信息
eureka.instance.instance-id = provicer01-8001
#8001
# 服务端口号
server.port = 8002
# 数据库配置
spring.datasource.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/demo2?
# 人性化显示出服务的信息
eureka.instance.instance-id = provicer02-8002
#8001
# 服务端口号
server.port = 8003
# 数据库配置
spring.datasource.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/demo3?
# 人性化显示出服务的信息
eureka.instance.instance-id = provicer03-8003
对比可以看出以下三点:
Eureka 集群还是使用前面的 7001、7002 和 7003,首先我们启动 Eureka 集群,然后分别启动 8001、8002 和 8003 三个订单服务。
测试:http://localhost:7001
可以看到三个订单服务都已经注册到Eureka服务上了
接下来启动消费者服务测试:启动consumer端
访问:http://localhost:9001/consumer/order/get/2
第一次:
第二次:
第三次:
可以看到Ribbon 的默认负载均衡算法是轮询,dbsource的值一在 microservice01、microservice02 和 microservice03 之间轮询切换(这个值是我在三个数据库中设置的不同的值,就是为了在这展示,方便看到效果),这就说明了,Ribbon 的负载均衡已经起作用了,客户端会轮询的根据服务名,从 8001、8002 和 8003 之间切换访问,从而达到负载均衡的效果。
Ribbon 自带的负载均衡策略有如下几个:
自定义Ribbon负载均衡算法,在配置类中new RandomRule() 制定负载均衡算法!
/**
* 配置RestTemplate
* @author shengwu ni
*/
@Configuration
public class RestTemplateConfig {
/**
* '@LoadBalanced'注解表示使用Ribbon实现客户端负载均衡
* @return RestTemplate
*/
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
/**
* 指定其他负载均衡策略
* @return IRule
*/
@Bean
public IRule myRule() {
// 指定重试策略:随机策略
return new RandomRule();
}
}
Spring Cloud基本Eureka客户端使用Ribbon实现负载均衡!