Spring Cloud Ribbon实现客户端负载均衡
原创
©著作权归作者所有:来自51CTO博客作者zhuhuix的原创作品,请联系作者获取转载授权,否则将追究法律责任
文章目录
背景
- 负载方案分为两种:一种是集中式负载均衡,在服务调用者和服务提供方之间使用独立的代理方式进行负载处理,比如lvs+nginx方案。
- 另一种则是客户端自己做负载均衡,服务调用者可根据自己的情况灵活做负载,Ribbon就属于这种情况。

一、搭建Eureka服务治理环境
- 创建Eureka服务器
- 创建服务提供方
- 创建服务调用者
以上请参考《实战Spring Cloud微服务治理组件Eureka》
二、创建服务集群
# 商品服务集群节点1
server.port=8080
spring.application.name=goods-service
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
# 商品服务集群节点2
server.port=8070
spring.application.name=goods-service
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
/**
* 商品服务-模拟返回商品列表
*/
@RestController
@RequestMapping("api/goods")
public class GoodsService {
private final static Logger logger = LoggerFactory.getLogger(GoodsService.class);
@Value("${spring.application.name}")
private String service;
@Value("${server.port}")
private String port;
// 返回商品列表
@GetMapping
public List<Goods> getAllGoods() {
List<Goods> goods = new ArrayList<>();
goods.add(new Goods("电脑", 10));
goods.add(new Goods("手机", 20));
goods.add(new Goods("书籍", 30));
logger.info(LocalDateTime.now()+" "+service+":"+port+" used!");
return goods;
}
}
- 注册服务:这时候在Eureka控制台可以看到GOODS-SERVICE服务下由两个节点组成了集群服务。

三、客户端调用服务
server.port=8081
spring.application.name=user-consumer
# 服务调用者不需要向服务中心进行注册
eureka.client.register-with-eureka=false
# 向eureka服务器获取服务列表
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
# 调用商品服务的地址
goods-service.url=http://GOODS-SERVICE/
- 通过@LoadBalanced注解,使用Ribbon组件进行负载均衡控制
/**
* 用户消费者启动类
*/
@EnableEurekaClient
@SpringBootApplication
public class UserConsumerApplication {
// 向Spring注册一个RestTemplate Bean
@Bean
// 通过@LoadBalanced注解,即使用Ribbon组件进行负载均衡控制
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(UserConsumerApplication.class, args);
}
}
/**
* 用户消费者--调用eureka服务器中的商品服务,并对外提供RestFul接口测试
*/
@RestController
@RequestMapping("user/")
public class UserConsumer {
@Autowired
private RestTemplate restTemplate;
@Value("${goods-service.url}")
private String url;
@GetMapping("/goods")
public User getUserGoods() {
User user = new User();
// 调用商品微服务
Object response = restTemplate.getForEntity(url + "api/goods", Object.class).getBody();
try {
user.setName("jack");
user.setGoods((List<GoodsDTO>) response);
} catch (Exception e){
throw new RuntimeException(e.getMessage());
}
return user;
}
}
- 使用HttpClient工具进行测试

- 观察服务集群中两个节点的日志信息,可以发现负载均衡已经起作用,服务调用者的请求被平均分配到了集群中的两个节点上。


四、自定义负载均衡策略
- Ribbon默认的负载策略是轮询,同时也提供了很多其他的策略,能够让用户根据自身的业务需求进行选择。
| |
RoundRobinRule
| 轮询选择
|
RandomRule
| 随机选择一个Server
|
WeightedResponseTimeRule
| 根据响应时间分配一个Weight(权重),响应时间越长,Weight越小,被选中的可能性越低
|
BestAvailabl
| 选择一个最小的并发请求的Server,逐个考察Server,如果Server被标记为错误,则跳过,然后再选择ActiveRequestCount中最小的Server
|
…
| …
|
- 客户端增加一个自定义策略配置文件:将负载均衡策略设为随机
/**
* 自定义负载均衡策略配置
*/
@Configuration
public class RibbonConfig {
@Bean
public IRule ribbonRule() {
return new RandomRule(); //设置负载均衡的规则为随机
//return new RoundRobinRule(); //默认的轮询策略
}
}
/**
* 用户消费者启动类
*/
@EnableEurekaClient
@SpringBootApplication
// 指定对调用商品服务时启用自定义策略
@RibbonClient(name = "GOODS-SERVICE", configuration = RibbonConfig.class)
public class UserConsumerApplication {
// 向Spring注册一个RestTemplate Bean
@Bean
// 通过@LoadBalanced注解,启用负载均衡
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(UserConsumerApplication.class, args);
}
}
- 再次使用HttpClient工具进行测试,观察服务集群节点的日志信息:原有的轮询策略已变成了随机策略。


小结
- Ribbon是Spring Cloud组件框架中实现客户端负载均衡的组件,可以让我们的服务调用具备负载均衡的能力。
- 通过Spring Cloud Ribbon的封装,我们在微服务架构中使用客户端负载均衡调用非常简单,只需要如下两步:
1. 服务提供者通过集群方式注册到Eureka服务中心。
2. 服务消费者直接通过调用被@LoadBalanced注解修饰过的RestTemplate来实现面向服务的接口调用。