1. 负载均衡
1.1. 负载均衡介绍
随着互联网时代的到来,流量增加、高并发和数据海量的问题也逐步到了,在计算机系统和网络架构中,如果使用单体服务往往难以承受高并发和大负载的请求,容易导致系统性能下降甚至崩溃,这就需要我们架构师们从水平、垂直两个方面解决这些问题
- 垂直扩展: 网络发展初期解决上述问题是通过增加服务器的硬件能力:网络、CPU、内存、磁盘等方面提升服务器处理能力,但是单体服务器总是存在瓶颈,一旦到达瓶颈就很难再提升,不然就要付出极大成本,显然不符合分布式设计理念。
- 水平扩展: 通过集群部署,将单台服务器请求压力,分摊给多个服务器上,集群中的服务器通常被设计成无状态。但是如何将请求(流量)分摊到各个服务器上?这就引出了今天要讲的概念负载均衡概念。
负载均衡(Load Balance)
- 作用:是如今高并发,高可用系统中不可缺少的关键组件。
- 目标:尽量将请求(流量)安装系统架构的设计发送(如何发送,通过负载均衡算法实现)到集群的多个服务器上,从而实现系统整体的响应速度和可用性。
1.2. 负载均衡分类
负载均衡可以从软件和硬件两个角度进行分类。这两种分类方式是基于负载均衡的实现方式和部署环境的不同。
1.2.1. 软件负载均衡
软件负载均衡是通过在软件层面上实现负载均衡功能,常见的软件负载均衡器有:
- Nginx:一个开源的高性能的Web服务器和反向代理服务器,具备负载均衡的功能。
- HAProxy:一个开源的高性能的TCP/HTTP负载均衡器,适用于高并发和高可靠性的环境。
- Apache HTTP Server:一个广泛使用的Web服务器,也可以作为反向代理服务器实现负载均衡。
- LVS(Linux Virtual Server):一个基于Linux内核的开源负载均衡软件,支持多种负载均衡算法。
适用场景:软件负载均衡器通常可以在通用服务器上部署,并且具有灵活性和可定制性,适用于中小型应用环境。
1.2.2. 硬件负载均衡
硬件负载均衡是通过专用的物理设备来实现负载均衡功能,这些设备通常具备更强大的处理能力和专门优化的负载均衡算法。常见的硬件负载均衡器有:
- F5 BIG-IP:一种商业化的硬件负载均衡器,广泛用于企业级应用和数据中心的负载均衡场景。
- Citrix NetScaler:一种商业化的硬件负载均衡器和应用交付控制器,支持高性能的负载均衡和应用加速功能。
- Brocade ADX:一种高性能的硬件负载均衡器,适用于大规模数据中心和云计算环境。适用场景:硬件负载均衡器是基于专用硬件设备的高性能解决方案,适用于大规模、高吞吐量的应用场景,提供更强大的负载均衡能力和扩展性。
1.3. 负载均衡算法
为了不脱离本次文章重点,我们只说一下有哪些常见的负载均衡算法:
- 轮询(Round Robin):将请求按照顺序依次分配给每个服务器。每次接收到请求时,负载均衡器会选择下一个服务器来处理请求,从而实现均衡负载。
- 加权轮询(Weighted Round Robin):给每个服务器设置一个权重值,根据权重来决定分配请求的比例。具有较大权重的服务器将获得更多的请求,可以根据服务器的性能、处理能力等因素进行调整。
- 最少连接(Least Connections):选择当前连接数最少的服务器来处理请求。负载均衡器会监测服务器的连接数,并将新的请求发送到连接数最少的服务器上,以实现负载均衡。
- 随机(Random):随机选择一个服务器来处理请求。简单且高效,但无法考虑服务器的负载情况,可能导致某些服务器过载。
- IP 哈希(IP Hash):根据客户端的 IP 地址进行哈希运算,将相同 IP 的请求发送到同一台服务器上。这样可以保证同一个客户端的请求始终由同一台服务器处理,适用于一些需要保持会话的应用场景。
- URL 哈希(URL Hash):根据请求的 URL 进行哈希运算,将相同 URL 的请求发送到同一台服务器上。适用于需要保持访问一致性的应用场景,例如缓存或分布式数据存储。
除了以上常见的负载均衡算法,还有其他更复杂的算法,如一致性哈希算法、最短响应时间算法等。这些算法根据不同的需求和场景选择合适的服务器,以实现更细粒度的负载均衡。在实际应用中,可以根据具体的系统架构和性能要求选择适合的负载均衡算法。
2. Ribbon负载均衡
SpringCloud底层其实是利用了一个名为Ribbon的组件,来实现负载均衡功能的。原理图如下:
ribbon的maven依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
注意:再order-servie和user-service服务中没有添加该依赖,但是实际上还是使用Ribbon进行负载均衡。
思考:为什么没有添加ribbon依赖还能使用该组件
因为再Eureka-client的依赖中已经集成ribbon的依赖
2.1. Ribbon负载均衡策略
Ribbon的负载均衡算法都定义再IRule接口中,有多个实现类
实现类的含义如下:
内置负载均衡规则类 |
规则描述 |
RoundRobinRule |
简单轮询服务列表来选择服务器。 |
AvailabilityFilteringRule |
对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。 |
WeightedResponseTimeRule |
为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。 |
ZoneAvoidanceRule |
以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。 |
BestAvailableRule |
忽略那些短路的服务器,并选择并发数较低的服务器。 |
RandomRule |
随机选择一个可用的服务器。 |
RetryRule |
重试机制的选择逻辑 |
默认的实现就是ZoneAvoidanceRule,是一种轮询方案
2.2 自定义负载均衡策略
通过定义IRule实现可以修改负载均衡规则,有两种方式:
- 代码声明注册
- 配置文件声明配置
2.2.1. 代码声明式注册
在OrderConfig
中定义新的规则方式,并且全局生效
@Bean
public IRule randomRule(){
return new RandomRule();
}
注意:添加过该配置后,必须重启服务
2.2.2. 配置文件式配置
在order-service的application.yml文件中,添加新的配置也可以修改规则:
user-service: # 给某个微服务配置负载均衡规则,这里是user-service服务
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则
注意,一般用默认的负载均衡规则,不做修改。
2.3. 饥饿加载
Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。
- 修改饥饿加载前启动日志
- 而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:
ribbon:
eager-load:
enabled: true
clients: user-service
3.总结
Spring Cloud Ribbon作为Spring Cloud的重要组成部分,为我们提供了强大而灵活的负载均衡解决方案。通过本文的介绍,你已经了解了Spring Cloud Ribbon的基本概念和使用方法,并学会了如何自定义负载均衡规则。希望本文能够帮助你构建更高效、稳定的微服务架构。如果你对Spring Cloud Ribbon还有更多的疑问,请随时留言。感谢阅读!
思考:
- Ribbon是什么?解决了什么问题?
- Ribbon实现的是客户端,还是服务端负载均衡?
- Ribbon如何实现负载均衡?
- 还有哪些技术点可以实现负载均衡?
- 负载均衡算法?如何实现?还有哪些技术有体现