最新版Spring Cloud Alibaba微服务架构-Ribbon负载均衡篇
Posted DT辰白
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最新版Spring Cloud Alibaba微服务架构-Ribbon负载均衡篇相关的知识,希望对你有一定的参考价值。
文章目录
前言
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。
一、Ribbon核心概念
Raibbon是基于Netflix Ribbon实现的一套客户端负载均衡工具。Raibbon客户端提供了一系列的配置,如超时、重试、负载均衡等,对Spring Cloud Ribbon的理解和使用,对于我们使用Spring Cloud来构建微服务非常重要,比如微服务之间的调用,API网关的转发请求等,实际上都是通过Ribbon来完成的。
通俗的来说:Ribbon = 负载均衡 + RestTemplate
这里提到了一个词,叫做客户端负载均衡,那么可能会想到我们的nginx,那么Nginx是客户端负载均衡吗?不是,Nginx实际上是一种集中式负载均衡(服务器端负载均衡),并不属于客户端负载均衡范畴。那么这两者的区别是什么呢?
二、服务器端负载均衡和Riboon客户端负载均衡
1、服务器端负载均衡:
服务端负载均衡又分为两种,一种是硬件负载均衡,还有一种是软件负载均衡。
例如Nginx,是软件负载均衡,通过Nginx进行负载均衡,先发送请求,然后通过负载均衡算法,在多个服务器之间选择一个进行访问;即在服务器端再进行负载均衡算法分配,我们来看一张图,使用Nginx做的负载均衡策略。
2、Riboon客户端负载均衡:
例如spring cloud中的ribbon,客户端会有一个服务器地址列表,在发送请求前通过负载均衡算法选择一个服务器,然后进行访问,这是客户端负载均衡;即在客户端就进行负载均衡算法分配。来直接上图,下图所示是我们本篇文章要实现的Ribbon负载均衡策略。
三、Ribbon策略
当我们在 RestTemplate 上添加 @LoadBalanced 注解后,就可以用服务名称来调用接口了,当有多个服务的时候,还能做负载均衡。然而Ribbon客户端组件提供一系列完善的配置项,如连接超时,重试等,并且我们还能够使用Ribbon实现自定义的负载均衡策略。
负载均衡常用策略方式:
- 默认为轮训的策略方式
- 随机
- 重试(如果获取服务失败,在指定时间内进行重试,获取可用服务)
- 过滤掉出故障的服务,选择一个最小并发量的服务
如下图为负载均衡轮训算法的实现:
四、Ribbon配置使用
这里我们使用Nacos作为注册中心,模拟订单服务于库存服务之间的调用,使用Ribbon作为客户端的负载均衡实现,他的配置方式很简单,下面我们就搭建好以下三个服务,准备实操一波。
服务名称 | 端口号 |
---|---|
dt-stock-service | 8083 |
dt-stock-service | 8082 |
dt-order-service | 8081 |
这里我们的库存服务为两个,订单服务为一个,通过订单服务调用库存服务,实现Ribbon的负载均衡,首先是订单服务启动类,我们把RestTemplate 注册进来,这里我们使用RestTemplate 来实现服务之间的调用,RestTemplate 只需要加上 @LoadBalanced 注解后,就可以用服务名称来调用接口了,既能实现Ribbon的负载均衡策略。
@SpringBootApplication
@EnableDiscoveryClient
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
订单服务控制器调用接口如下:
@RestController
@RequestMapping(value = "order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("test")
public String getOrder() {
String msg = restTemplate.getForObject("http://dt-stock-service/stock/test", String.class);
return "调用订单服务->>>"+msg;
}
}
我们通过服务名称的方式(dt-stock-service)来调用库存服务接口方法,然后我们再编写库存服务控制器接口方法:
@RestController
@RequestMapping(value = "/stock")
public class StockController {
@Value("${server.port}")
private String port;
@GetMapping("/test")
public String getStock() {
return "调用库存服务:"+port;
}
}
这里我们打印一下当前库存服务被调用的端口,以便观察Ribbon的负载均衡策略模式,服务架构如下。
我们启动8081订单服务,再依次启动8082、8083库存服务,服务启动之后,观察我们的注册中心服务实例变化,此时订单服务有一个实例,库存服务有两个实例,服务启动成功了,下面我们来发送接口测试:
发送请求:http://localhost:8081/order/test
第一次8083端口:
第二次8082端口:
一直发送接口请求测试,可以发现,都是8083和8082之间轮训切换调用,那就明白了,Ribbon默认的策略模式是轮询的方式,在文章开头我们说过Riboon的策略方式不止轮询,轮询只是它自身内部一种默认的实现方式,下面我们就来研究其他的几种常见的方式怎么玩?
五、配置自定义的负载均衡算法
1、按照权重实现负载均衡
Ribbon本身是没有权重的概念的, 那么如何才能实现代用权重的负载均衡呢? 我们在nacos中, 服务器的集群有一个权重的概念, 当给服务器设置了权重, 那么流量就可以根据权重比例分配到服务器上。
1.1 配置Ribbon
spring:
application:
name: dt-order-service
cloud:
nacos:
server-addr: 47.108.191.196:9091
discovery:
username: nacos
password: nacos
namespace: public
ribbon:
NFLoadBalancerRuleClassName: com.dt.springcloud.ribbon.config.GlobalRibbonConfig #指定全局的负载均衡算法
eager-load:
enabled: true #开启饥饿模式
clients: dt-stock-service #为哪些服务的名称开启饥饿加载,多个用逗号分隔
com.dt.springcloud.ribbon.config.GlobalRibbonConfig #指定全局的负载均衡算法类名
这里小编解释一下Ribbon为什么会有饥饿模式的配置:ribbon客户端不是在服务启动的时候加载的,所以可能第一次调用会很慢,甚至超时。
1.2 全局的负载均衡算法类
/**
* 全局设置自定义的权重负载均衡策略
* @author DT
* @date 2021/8/7 20:39
*/
@Configuration
public class GlobalRibbonConfig {
@Bean
public IRule getRule() {
// 实现带有权重的负载均衡策略
return new MyWeightRule();
}
}
1.3 自定义权重实现负载均衡
/**
* 自定义一个权重负载均衡策略
* @author DT
* @date 2021/8/7 20:32
*/
public class MyWeightRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties discoveryProperties;
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) { }
/**
* 自定义实现负载均衡策略的方法
*/
@Override
public Server choose(Object key) {
try {
// 调用父类方法, 获取当前使用的负载均衡器
BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
// 获取当前服务的名称
String serviceName = baseLoadBalancer.getName();
// 获取nacos的服务发现API
NamingService namingService = discoveryProperties.namingServiceInstance();
// nacos实现了权重的负载均衡算法
Instance instance = namingService.selectOneHealthyInstance(serviceName);
// 打印输出
String threadName = Thread.currentThread().getName();
System.out.println("线程->>>" + threadName + "->>>发送请求");
System.out.println("IP端口->>>"+instance.getIp()+":"+instance.getPort());
return new NacosServer(instance);
} catch (NacosException e) {
e.printStackTrace();
}
return null;
}
}
1.4 设置Nacos服务实例权重比例
我们一个设置为0.3, 另一个设置成0.7, 也就是说如果有10次请求, 基本上都是会打到8082端口上的,因为8082的权重最高,打到它的接口数量应该是最多的。
1.4 测试负载均衡
http://localhost:8081/order/test
触发10次请求,基本7次左右都会打到8082服务上面。
六、Ribbon常用配置
ribbon:
ConnectTimeout: 1000 #服务请求连接超时时间(毫秒)
ReadTimeout: 3000 #服务请求处理超时时间(毫秒)
OkToRetryOnAllOperations: true #对超时请求启用重试机制
MaxAutoRetriesNextServer: 1 #切换重试实例的最大个数
MaxAutoRetries: 1 #切换实例后重试最大次数
NFLoadBalancerRuleClassName: com.dt.springcloud.ribbon.config.GlobalRibbonConfig #修改负载均衡算法
在我们文章当中,使用的是全局配置,当然你也可以指定针对单独的服务配置:
#服务名
dt-order-service:
ribbon:
ConnectTimeout: 1000 #服务请求连接超时时间(毫秒)
ReadTimeout: 3000 #服务请求处理超时时间(毫秒)
OkToRetryOnAllOperations: true #对超时请求启用重试机制
MaxAutoRetriesNextServer: 1 #切换重试实例的最大个数
MaxAutoRetries: 1 #切换实例后重试最大次数
NFLoadBalancerRuleClassName: com.dt.springcloud.ribbon.config.GlobalRibbonConfig #修改负载均衡算法
总结
好了,以上内容就是今天的输出,后面我们再继续深入研究微服务其他的组件的使用以及原理剖析,创作不易,喜欢的请关注小编CSDN:https://blog.csdn.net/qq_41107231 以及掘金:https://juejin.cn/user/3940246036699848
以上是关于最新版Spring Cloud Alibaba微服务架构-Ribbon负载均衡篇的主要内容,如果未能解决你的问题,请参考以下文章
SpringCloud - Spring Cloud Alibaba