基于Ribbon实现负载均衡
Ribbon是Spring Cloud 的一个组件,它可以让我们使用一个注解就能轻松的搞定负载均衡。
Ribbon负载均衡机制
策路名 | 策略描述 | 策略描述 |
---|---|---|
BestAvailableRule | 选择一个最小的并发请求 | 逐个考察Server,如果Server被tripped了,BestAvailableRule 则忽略,在选择其中ActiveRequestsCount最小的server |
AvailabilitvRilterinRule | 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的 server(active connections 超过配置的阔值) | 使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就是检查status里面的记录的各个server的运行状态。 |
WeightedResponseTimeRule | 根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低 | 一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个计算一个weight值。weight的计算也比较简单,responsetime减去每个server自己的平均的responsetime是server的权重。当刚开始运行,没有形成status时,使用roubine策略选择server。 |
RetryRule | 对选定的负载均衡策略机上重试机制 | 在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server |
RoundRobinRule | 轮询方式轮询选择server | 轮询index, 选择index对用位置的server |
ZoneAvoidanceRule | 复合判断server所在区域的性能和server的可用性选择server | 使用ZoneAvoidancPredicate和AvailabilityPredicate来判断是否可以选择某个server,前一个判判定一个zone的运行性能是否可用,剔除不可用的zone的所有的server,AvailabilityPredicate用于过滤掉连接数过多的server。 |
我们常用机制:1.BestAvailableRule 2.RoundRobinRule 3.ZoneAvoidanceRule
用例
-
第一步:在调用的微服务的yml文件配置
-
第二步:在RestTemplate的生成方法上添加@LoadBalanced注解
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
- 第三步:修改服务调用方法,直接调用服务名
/**
* Ribbon负载均衡
* @param id
* @return
*/
@RequestMapping("/getOrderByProductId")
public String getOrderInfo(@RequestParam(name = "id",value = "id") Integer id){
// 通过nacos服务列表中的服务名,获取要访问的微服务,因为同一个服务器可能会有一个服务集群,所以返回的是一个列表
String productInfo = restTemplate.getForObject("http://service-product/product/info/getInfoById?id=" + id,String.class);
log.info("id={},返回结果是{}",id,productInfo);
return productInfo;
}
/**
* // 随机调用机制
*/
// @RequestMapping("/getOrderByProductId")
// public String getOrderInfo(@RequestParam(name = "id",value = "id") Integer id){
// // 通过nacos服务列表中的服务名,获取要访问的微服务,因为同一个服务器可能会有一个服务集群,所以返回的是一个列表
// List<ServiceInstance> serviceInstanceList = discoveryClient.getInstances("service-product");
// // 随机调用机制
// int index = new Random().nextInt(serviceInstanceList.size());
// ServiceInstance serviceInstance = serviceInstanceList.get(index);
// String productInfo = restTemplate.getForObject("http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() +"/product/info/getInfoById?id=" + id,String.class);
// log.info("id={},返回结果是{}",id,productInfo);
// return productInfo;
// }