在微服务架构中,负载均衡是必须使用的技术,通过它来实现系统的高可用、集群扩容等功能。负载均衡可以分为两种:服务端负载均衡和客户端负载均衡。通常所说的负载均衡指服务器负载均衡,可通过硬件设备或软件来实现,硬件比如:F5、Array等,软件比如:LVS、Nginx等。
负载均衡按实现方式分类可区分为:服务端负载均衡(比如Nacos负载均衡)与客户端负载均衡。
SpringCloud Ribbon是基于客户端的负载均衡工具,它可以将面向服务的 REST 模板请求自动转换成客户端负载均衡的服务调用。执行过程如下图:
Ribbon
是由 Netflix 发布的负载均衡器,它有助于控制 HTTP 和 TCP 的客户端的行为。Ribbon 属于客户端负载均衡。
为 Ribbon 配置服务提供者地址后,Ribbon 就可基于某种负载均衡算法,自动的帮助服务消费者进行请求。同时 Ribbon 默认为我们提供了很多负载均衡算法,例如:轮询、随机算法等。
Ribbon 内置多种负载均衡策略,常用的分为以下几种。
轮询策略,Ribbon 默认策略。默认超过 10 次获取到的 server 都不可用,会返回个空的 server。
随机策略,如果随机到的 server 为 null 或者不可用的话。会不停地循环选取。
重试策略,定时限内循环重试。默认继承 RoundRobinRule,也持自定义注,RetryRule 会在每次选取之后,对选举的 server 进判断,是否为 null,是否 alive,并且在 500ms 内会不停地选取判断。而 RoundRobinRule 失效的策略是超过 10 次,RandomRule 没有失效时间的概念,只要 serverList 没都挂。
最小连接数策略,遍历 serverList,选取出可的且连接数最小的个 server。那么会调用 RoundRobinRule 重新选取。
可用过滤策略。扩展了轮询策略,会先通过默认的轮询选取个 server,再去判断该 server 是否超时可用、当前连接数是否超限,都成功再返回。
区域权衡策略。扩展了轮询策略,除了过滤超时和链接数过多的 server,还会过滤掉不符合要求的 zone 区域的所有节点,始终保证在个区域/机房内的服务实例进行轮询。
这里所有负载均衡策略名本质都是 com.netflix.loadbalancer 包下的类:
要更改微服务通信时采用的负载均衡策略也很简单,在 application.yml 中采用下面格式书写即可。
provider-service: #服务提供者的微服务id
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #设置对应的负载均衡类
当采用随机策略,杂乱的顺序说明随机策略已生效。
ILoadBalancer
:定义一系列的操作接口,比如选择服务实例。
IRule
:算法策略,内置算法策略来为服务实例的选择提供服务。
ServerList
:负责服务实例信息的获取,可以获取配置文件中的,也可以从注册中心获取。
ServerListFilter
:过滤掉某些不想要的服务实例信息。
ServerListUpdater
:更新本地缓存的服务实例信息。
IPing
:对已有的服务实例进行可用性检查,保证选择的服务都是可用的。
如果需要自定义相关组件,需要实现上述接口。
Ribbon 的使用方式主要分为下面这三种,
配置一个服务列表,数据格式为 IP + PORT,可以固定写几个服务列表,也可以从别处读取,比如注册中心。
构建一个负载实例,将服务列表传入,再指定对应的负载均衡策略,RandomRule 是随机策略。具体的应用逻辑写在 call 方法里,call 方法的参数是 Server 对象,Server 也就是我们第一步构建的服务列表信息,得到 Server 后就可以获取到对应的 IP 和端口,然后进行接口的调用。
代码案例如下:
/**
* 轮询请求测试
*/
@Test
public void roundRobinRuleTest(){
// 服务列表
List serverList = Arrays.asList(new Server("localhost", 8080),
new Server("localhost", 8081),
new Server("localhost", 8082));
// 构建负载实例
BaseLoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(serverList);
loadBalancer.setRule(new RoundRobinRule());
// 调用5次来测试效果
for (int i = 0; i < 6; i++) {
String result = LoadBalancerCommand.builder().withLoadBalancer(loadBalancer).build()
.submit(new ServerOperation() {
@Override
public Observable call(Server server) {
try {
String addr = "http://" + server.getHost() + ":" + server.getPort();
System.out.println("调用地址:" + addr);
return Observable.just("");
} catch (Exception e) {
return Observable.error(e);
}
}
}).toBlocking().first();
System.out.println("调用结果:" + result);
}
}
RestTemplate 是 Spring 提供的用于访问 Rest 服务的客户端,RestTemplate 提供了多种便捷访问远程 HTTP 服务的方法,能够大大提高客户端的编写效率。
将 RestTemplate 和 Ribbon 整合起来,只需要在配置 RestTemplate 实例的时候,加一个 @LoadBalanced 的注解,这样 RestTemplate 在调用接口时,就不需要用固定的 IP 加端口的方式调用接口,而是可以用服务名称的方式进行接口的调用,自动具备客户端负载均衡的效果。
// RestTemplate 配置类
@Configuration
public class RestConfiguration {
@Bean
// @LoadBalanced 注解让RestTemplate 能够直接使用服务名称调用对应的接口
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@Autowired
private RestTemplate restTemplate;
@GetMapping("/get")
public Object get() {
User user = restTemplate.getForEntity("http://system-service/user/get?id=1", User.class).getBody();
//User user = restTemplate.getForEntity("http://localhost:8084/user/get?id=1", User.class).getBody();
return user;
}
本文内容到此结束了,
如有收获欢迎点赞??收藏??关注,您的鼓励是我最大的动力。
如有错误疑问??欢迎各位大佬指出。
主页:的博客汇总???保持热爱,奔赴下一场山海。???
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦