负载均衡

什么是负载均衡

  • 负载均衡(Load Balancing)是指在分布式系统中,将工作负载(Workload)平均分配给多个服务器或计算机资源,以提高系统的性能、可靠性和可扩展性。
    在这里插入图片描述

生活场景

  • 我们在日常生活中经常免不了要去一些比较拥挤的地方,比如地铁站、火车站、电影院、银行等。无论是买票,还是排队入场,这些场所一般都会设置多个服务点或者入口的。如果没有人引导的话,大多数情况下,最近的入口会挤满人。而哪些距离较远的服务点或者入口就宽松很多。
    在这里插入图片描述
  • 这种情况下,就会大大浪费资源,因为如果可以把这些排队的人很好的分散到各个入口的话会大大缩短排队时间。其实,软件的建设也是一样的。为了提升系统的服务能力,很多网站采用集群部署,就像话剧院有多个入口一样。这时候,就需要一个协调者,来均衡的分配这些用户的请求,可以让用户的可以均匀的分派到不同的服务器上。

在这里插入图片描述

为什么需要负载均衡

负载均衡是一种分配和管理网络流量的技术,主要用于确保网络服务的高可用性、可扩展性和性能优化。以下是需要负载均衡的主要原因:

  1. 高可用性:负载均衡可以将流量分配到多个服务器上,当其中一台服务器发生故障时,流量会自动转移到其他正常工作的服务器上,从而确保服务的连续性和可用性。

  2. 扩展性:负载均衡可以将流量分布到多个服务器上,允许系统根据需要动态地添加或删除服务器。这样可以更好地应对流量的增长和业务的扩展。

  3. 性能优化:负载均衡可以根据服务器的负载情况将流量分配到最空闲或最适合处理当前请求的服务器上,从而提高系统的响应速度和吞吐量。

  4. 故障恢复:当一台服务器发生故障时,负载均衡可以自动将流量转移到其他正常工作的服务器上,从而实现快速的故障恢复,减少服务中断时间。

  5. 节约成本:通过负载均衡,可以充分利用服务器的资源,提高服务器的利用率,从而减少不必要的硬件投入和维护成本。

总的来说,负载均衡是一种提高系统性能、可用性和可扩展性的重要技术,适用于各种网络应用和服务。

负载均衡手段

负载均衡总的来说有两种实现手段

一种是服务端负载均衡器,另一种是客户端负载均衡器

  • 服务端负载均衡器的问题是,它提供了更强的流量控制权,但无法满足不同的消费者希望使用不同负载均衡策略的需求,而使用不同负载均衡策略的场景确实是存在的,所以客户端负载均衡就提供了这种灵活性。
  • 客户端负载均衡也有其缺点,如果配置不当,可能会导致服务提供者出现热点,或者压根就拿不到任何服务的情况
  • 服务端负载均衡器和客户端负载均衡器的区别如下图所示
    在这里插入图片描述在这里插入图片描述
  • 客户端负载均衡器的实现原理是通过注册中心,如 Nacos,将可用的服务列表拉取到本地(客户端),再通过客户端负载均衡器(设置的负载均衡策略)获取到某个服务器的具体 ip 和端口,然后再通过 Http 框架请求服务并得到结果,其执行流程如下图所示:
    在这里插入图片描述

负载均衡具体可以通过多种手段来实现

以下是一些常见的负载均衡手段:

  1. 基于DNS的负载均衡:通过使用DNS来将流量分布到不同的服务器上。在DNS解析请求时,返回多个服务器的IP地址,客户端根据返回的IP地址选择一个服务器进行连接。

  2. 集中式负载均衡:使用专门的负载均衡设备(如负载均衡器或负载均衡服务器)来分发流量。这些设备通常位于服务器和客户端之间,根据特定的算法将流量分配到不同的服务器上。

  3. 分布式负载均衡:将负载均衡的功能分散到多个服务器上,每个服务器都负责分发一部分的流量。这种方式可以提高系统的扩展性和容错性。

  4. 会话保持(Session Affinity):某些应用需要保持与特定服务器的会话状态,这需要负载均衡器将同一用户的请求始终分发到同一台服务器上,以保证会话的连续性。

  5. 基于内容的负载均衡:根据请求的内容或URL等特征来进行负载均衡。例如,可以根据请求的路径将静态资源请求分发到专门处理静态资源的服务器。

  6. 哈希负载均衡:根据客户端请求的特征(如IP地址、用户标识等)计算哈希值,将相同哈希值的请求定向到同一台服务器上。这可以保证相同请求始终分发到同一台服务器上。

需要注意的是,不同的负载均衡手段适用于不同的场景和需求,需要根据具体的应用和系统来选择合适的负载均衡策略。

SpringCloud中的负载均衡组件

  • 在spring cloud H版大部分使用的负载均衡组件就是Ribbon和OpenFegin
  • 而在spring cloud跟新后官方宣布在 SpringCloud 2020版本以后 SpringCloud剔除掉了 除了eureka-server与 eureka-client 除外的所有 Netflix组件,spring也给出了使用spring cloud Loadbalancer替代的方案
  • 但就在目前,Ribbon以及OpenFegin仍然是主流的负载均衡的方案

Ribbon VS Nginx负载均衡区别

  • Nginx是服务器负载均衡,客户端所有请求都会交给Nginx,然后由Nginx实现转发请求。即负载均衡是由服务端实现的。
  • Ribbon本地负载均衡,在调用微服务接口时候,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用技术。
集中式LB
  • 即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方;
进程内LB
  • 将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。
  • Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。

在这里插入图片描述在这里插入图片描述

Ribbon

  • Ribbon 是 Spring Cloud 技术栈中非常重要的基础框架,它为 Spring Cloud 提供了负载均衡的能力
  • 比如 Fegin 和 OpenFegin 都是基于 Ribbon 实现的,就连 Nacos 中的负载均衡也使用了 Ribbon 框架。
  • Ribbon 框架的强大之处在于,它不仅内置了 7 种负载均衡策略,同时还支持用户自定义负载均衡策略,所以其开放性和便利性也是它得以流行的主要原因。

简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。

  • Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。
  • 简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。
  • 我们很容易使用Ribbon实现自定义的负载均衡算法。

Ribbon的工作原理

在这里插入图片描述

Ribbon在工作时分成两步

  • 第一步先选择 EurekaServer ,它优先选择在同一个区域内负载较少的server.
  • 第二步再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址。
  • 其中Ribbon提供了多种策略:比如轮询、随机和根据响应时间加权。

使用

1.提供者集群

复制几个demo-user-provider服务,只需要保证端口不一致就可以,其他配置一致,尤其是服务名称必须要一致,因为对于注册中心而言,多个demo-user-provider服务实例的作用都是一样的,就像是在食堂打饭,多个窗口的饭是一样的,就是多个实例,但是都同属于一个服务
在这里插入图片描述

2.引入依赖

  • 其实引入了Eureka的坐标即可,spring-cloud-starter-netflix-eureka-client自带了spring-cloud-starter-ribbon引用
      <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

在这里插入图片描述

4.测试

访问:localhost:8084/consumer/doLogin
在这里插入图片描述

Ribbon的负载均衡策略

核心组件

  • 根据特定算法中从服务列表中选取一个要访问的服务
  • 通过在容器中注入这个接口的不同实现类就可以实现不同的负载均很算法
    在这里插入图片描述

轮询

  • 由上图可知,Ribbon 默认的负载均衡策略是轮询模式
  • 轮询策略:RoundRobinRule,按照一定的顺序依次调用服务实例。
  • 比如一共有 3 个服务,第一次调用服务 1,第二次调用服务 2,第三次调用服务3,依次类推

随机

  • 随机策略:RandomRule,从服务提供者的列表中随机选择一个服务实例

代码案例

添加配置类

@Configuration
public class RibbonConfiguration {

    @Bean
    public IRule myRule() {
        return new RandomRule(); // 返回随机策略的Bean
    }
}

再访问:
在这里插入图片描述

权重

  • 权重策略:WeightedResponseTimeRule,根据每个服务提供者的响应时间分配一个权重,响应时间越长,权重越小,被选中的可能性也就越低。
  • 它的实现原理是,刚开始使用轮询策略并开启一个计时器,每一段时间收集一次所有服务提供者的平均响应时间,然后再给每个服务提供者附上一个权重,权重越高被选中的概率也越大

代码案例

配置类

@Configuration
public class RibbonConfiguration {

    @Bean
    public IRule myRule() {
        //return new RandomRule(); // 返回随机策略的Bean
        return new WeightedResponseTimeRule(); // 返回权重策略的Bean
    }
}

最小连接数

  • 最小连接数策略:BestAvailableRule,也叫最小并发数策略,它是遍历服务提供者列表,选取连接数最小的⼀个服务实例。
  • 如果有相同的最小连接数,那么会调用轮询策略进行选取

代码案例

@Configuration
public class RibbonConfiguration {

    @Bean
    public IRule myRule() {
        //return new RandomRule(); // 返回随机策略的Bean
        //return new WeightedResponseTimeRule(); // 返回权重策略的Bean
        return new BestAvailableRule(); // 返回最小连接数策略的Bean
    }
}

重试

  • 重试策略:RetryRule,按照轮询策略来获取服务,如果获取的服务实例为 null 或已经失效,则在指定的时间之内不断地进行重试来获取服务
  • 如果超过指定时间依然没获取到服务实例则返回 null

代码案例

@Configuration
public class RibbonConfiguration {
    @Bean
    public IClientConfig ribbonClientConfig() {
        DefaultClientConfigImpl config = new DefaultClientConfigImpl();
        return config;
    }

    @Bean
    public IRule myRule(IClientConfig config) {
        //return new RandomRule(); // 返回随机策略的Bean
        //return new WeightedResponseTimeRule(); // 返回权重策略的Bean
        config.setProperty(IClientConfigKey.Keys.ConnectTimeout,2000);// 设置连接超时为2000毫秒
        config.setProperty(IClientConfigKey.Keys.ReadTimeout,5000);// 设置读取超时为5000毫秒
        return new BestAvailableRule(); // 返回最小连接数策略的Bean
    }
}

可用性敏感策略

  • 可用敏感性策略:AvailabilityFilteringRule,先过滤掉非健康的服务实例,然后再选择连接数较小的服务实例

代码案例

@Configuration
public class RibbonConfiguration {

    @Bean
    public IRule myRule(IClientConfig config) {
        //return new RandomRule(); // 返回随机策略的Bean
        //return new WeightedResponseTimeRule(); // 返回权重策略的Bean
        //return new BestAvailableRule(); // 返回最小连接数策略的Bean
        return new AvailabilityFilteringRule(); // 返回可用性敏感策略的Bean
    }
}

区域敏感策略

  • 区域敏感策略:ZoneAvoidanceRule,根据服务所在区域(zone)的性能和服务的可用性来选择服务实例,在没有区域的环境下,该策略和轮询策略类似。

代码案例

@Configuration
public class RibbonConfiguration {

    @Bean
    public IRule myRule(IClientConfig config) {
        //return new RandomRule(); // 返回随机策略的Bean
        //return new WeightedResponseTimeRule(); // 返回权重策略的Bean
        //return new BestAvailableRule(); // 返回最小连接数策略的Bean
        //return new AvailabilityFilteringRule(); // 返回可用性敏感策略的Bean
        return new ZoneAvoidanceRule(); // 返回区域敏感策略的Bean
    }
}

配置方式修改负载均衡策略

demo-user-provider: # 远程调用的服务名称
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
  • 理解:在服务消费方,对远程调用的服务提供方做负载均衡,对该提供方所有的服务示例采用的负载均衡策略为XXX

总结

类 型说 明
WeightedResponseTimeRule权重:根据响应时间分配一个weight(权重),响应时间越长,weight越小,被选中的可能性越低
RoundRobinRule轮询:轮询选择server(此为默认的负载均衡策略)
RandomRule随机:随机选择一个server
ZoneAvoidanceRule区域敏感策略:复合判断server所在区域的性能和server的可用性选择server
RetryRule重试:在一个配置时间段内,当选择server不成功时一直尝试重新选择
BestAvailableRule最小连接:选择一个并发请求最小的server
AvailabilityFilteringRule可用性敏感策略:过滤掉那些因为一直连接失败而被标记为circuit tripped的server,并过滤掉那些高并发的server(active connections 超过配置的阈值)
  • Ribbon 为客户端负载均衡器,相比于服务端负载均衡器的统一负载均衡策略来说,它提供了更多的灵活性。
  • Ribbon 内置了 7 种负载均衡策略:轮询策略、权重策略、随机策略、最小连接数策略、重试策略、可用性敏感策略、区域性敏感策略
  • 并且用户可以通过继承 RoundRibbonRule 来实现自定义负载均衡策略。
Logo

欢迎加入西安开发者社区!我们致力于为西安地区的开发者提供学习、合作和成长的机会。参与我们的活动,与专家分享最新技术趋势,解决挑战,探索创新。加入我们,共同打造技术社区!

更多推荐