什么是负载均衡
负载均衡是微服务架构中非常重要且不得不去实施的内容,因为负载均衡对系统的高可用、网络压力的缓解起到了决定性的作用。
我们通常所说的负载均衡是指服务器端负载均衡,其中分为硬件负载均衡和软件负载均衡。硬件负载均衡主要通过在服务器节点之间安装专门用于负载均衡的设备,比如F5等;而软件负载均衡则是通过在服务器上安装一些具有负载均衡功能的软件来完成请求的分发工作,比如Nginx等。
客户端负载均衡与服务端负载均衡最大的不同点在于服务清单所存储的位置。客户端负载均衡中,所有客户端节点都维护着自己要访问的服务端清单,而这些清单来自于服务注册中心,比如Eureka。
什么是Spring Cloud Ribbon
Spring Cloud Ribbon 是一个客户端负载均衡的工具,它是基于Netflix Bibbon实现的。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模板请求自动转换成客户端负载均衡的服务调用。它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务之间的调用基本都是通过Ribbon来实现的。
如何使用 Spring Cloud Ribbon
通过Spring Cloud Ribbon 的封装,我们在微服务架构中使用客户端负载均衡非常简单,只需要两步:
- 服务提供者提供多个服务实例到服务注册中心;
- 服务消费者直接通过调用被**@LoadBalanced注解修饰过的RestTemplate**对象来实现服务的接口调用。
package com.wxw.example.springcloudeurekauser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class UserController {
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
@Autowired
RestTemplate restTemplate;
@RequestMapping(value = "helloUser",method = RequestMethod.GET)
public String helloUser(){
return restTemplate.getForEntity("http://hello-server/hello",String.class).getBody();
}
}
RestTemplate相关的方法
Get请求
在RestTemplate中,对Get请求可以通过两个方法进行调用。
- getForEntity()方法,该方法返回的是ResponseEntity对象,该对象是对HTTP请求响应的封装。
第一个参数表示要访问的服务地址;
第二个参数为返回ResponseEntity对象中body的类型;
第三个参数为调用服务的参数。 - getForObject()方法,该方法直接返回包装好的对象,即第2个参数的类型。
以上方法均有重载,具体可查看API。
POST请求
在RestTemplate中,对POST请求可以通过三个方法进行调用。
- postForEntity()方法,与getForEntity()方法类似。
第一个参数表示要访问的服务地址;
第二个参数为请求的对象;
第三个参数为响应的类型。 - postForObject()方法,与getForObject()方法类似。
- postForLocation()方法,提交请求并返回新资源的URI。
以上方法均有重载,具体可查看API。
PUT请求
在RestTemplate中,对PUT请求可以通过put()方法进行调用。
put()方法没有返回类型,参数与postForObject()基本一致。
DELETE请求
在RestTemplate中,对DELETE请求可以通过delete()方法进行调用。
Ribbon负载均衡策略
使用Spring Cloud Ribbon很简单,只需要简单的配置即可,Ribbon最核心的地方也就是负载均衡的算法。
IRule是负载均衡的接口,其实现类有如下几个:
- RandomRule,随机访问规则。
大致逻辑就是以服务的实例数为范围,使用线程安全的Random生成一个整型的随机数。
int index = this.chooseRandomInt(serverCount);
server = (Server)upList.get(index);
protected int chooseRandomInt(int serverCount) {
return ThreadLocalRandom.current().nextInt(serverCount);
}
-
RoundRobinRule,轮询访问规则。
大致逻辑是在服务实例数的范围内,通过一个int变量使用CAS原子性操作递增,来实现服务实例的轮询访问。
轮询规则中还有一个WeightedResponseTimeRule子类,加权轮询规则。
加权轮询会根据每个服务的运行响应时间为基础,选择处理性能最佳的服务器进行访问。 -
RetryRule,重试规则。
-
BestAvailableRule,最大可用策略,即先过滤出故障服务器后,选择一个当前并发请求数最小的。
-
AvailabilityFilteringRule,可用过滤策略,先过滤出故障的或并发请求大于阈值的一部分服务实例,然后再以线性轮询的方式从过滤后的实例清单中选出一个。
-
ZoneAvoiadanceRule,区域感知策略,先使用主过滤条件(区域负载器,选择最优区域)对所有实例过滤并返回过滤后的实例清单,依次使用次过滤条件进行过滤,最后对满足条件的服务器使用轮询选择一个服务器实例。
修改Ribbon负载均衡的默认规则
Spring Cloud Ribbon默认使用线性轮询的规则,可以通过配置去修改负载均衡的规则。
# 服务名加上ribbon.NFLoadBalancerRuleClassName=要使用的规则
provider-service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule