Spring Cloud LoadBalancer 负载均衡策略

Cloud Native Applications (spring.io)open in new window

LoadBalancer(负载均衡器)是一种用来分发网络或应用程序流量到多个服务器的技术。它可以防止任何单一服务的过载,通过分散负载来保持整个系统的平稳运行,保证系统的高可用性和可靠性。

负载均衡策略大体上分为两类:服务端的负载均衡和客户端的负载均衡。

  • 服务端负载均衡 (如 Nginx、F5):

​ 请求先到达一个中介(如负载均衡器设备或者服务,例如Nginx),由这个中介根据配置的策略将请求分发到后端的多个服务器中。 它对客户端是透明的,即客户端不需要知道有多少服务器以及它们的存在。

  • 客户端负载均衡 (如 Ribbon、Spring Cloud LoadBalancer)

    请求的分配逻辑由客户端持有,客户端直接决定将请求发送到哪一个服务器。也就是说在客户端负载均衡中,客户端通常具备一份服务列表,它知道每个服务的健康状况,基于这些信息和负载均衡策略,客户端会选择一个最适合的服务去发送请求。

常见的负载均衡策略

  • 轮询(Round Robin) 描述:轮询是最简单的负载均衡策略,它按顺序将每个新请求分配给下一个服务器。当到达列表末尾时,它会重新开始。 使用场景:适用于服务器性能相似且负载相对均衡的情况。
  • 加权轮询(Weighted Round Robin) 描述:与轮询类似,但给每个服务器分配一个权重。服务器的权重越高,分配给该服务器的请求就越多。 使用场景:适用于服务器性能不均或希望给特定服务器更多流量的情况。
  • 随机(Random) 描述:随机选择一个服务器来处理新的请求。 使用场景:适用于服务器数量较多且请求分布均匀的场景。
  • 加权随机(Weighted Random) 描述:类似于随机策略,但考虑服务器的权重。权重越高的服务器被选中的概率越大。 使用场景:当服务器性能不均匀时,希望根据性能分配不同的请求量。
  • 最小连接(Least Connections) 描述:选择当前连接数最少的服务器来处理新的请求。这种方法考虑了服务器的当前负载。 使用场景:适用于请求处理时间波动较大的场景。
  • 加权最小连接(Weighted Least Connections) 描述:与最小连接策略类似,但考虑了服务器的权重和当前连接数。 使用场景:当服务器性能不同且请求处理时间不一致时使用。
  • 基于资源(Resource Based) 描述:根据服务器的实际资源使用情况(如CPU、内存使用率)来分配请求。 使用场景:适用于资源敏感型应用,如高CPU或内存需求的应用。
  • IP哈希(IP Hash) 描述:根据请求的源IP地址进行哈希计算,然后分配到特定的服务器。这样可以保证来自同一IP地址的请求总是被发送到同一个服务器。 使用场景:适用于需要保持用户会话(session)一致性的场景。

Spring Cloud LoadBalancer 内置的两种负载均衡策略

Round-Robin-based 轮询负载均衡策略(默认的)

RoundRobinLoadBalancer:

private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {
        if (instances.isEmpty()) {
            if (log.isWarnEnabled()) {
                log.warn("No servers available for service: " + this.serviceId);
            }

            return new EmptyResponse();
        } else if (instances.size() == 1) {
            return new DefaultResponse((ServiceInstance)instances.get(0));
        } else {
            // 原子操作,保证了每次调用都会得到一个唯一的递增数值,& Integer.MAX_VALUE 这部分是一个位运算,它确保了如果 							// position 的值增加到超过 Integer.MAX_VALUE 时,不会产生负数。
            int pos = this.position.incrementAndGet() & Integer.MAX_VALUE;
            // 计算的是 pos 除以 instances 列表大小的余数,这保证了不论 pos 增长到多大,这个表达式的结果都是在 0 到 								// instances.size() - 1 的范围内,这样就可以循环地从服务实例列表中选择服务实例。
            ServiceInstance instance = (ServiceInstance)instances.get(pos % instances.size());
            return new DefaultResponse(instance);
        }
    }

Random 随机负载均衡策略

RandomLoadBalancer:

private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {
        if (instances.isEmpty()) {
            if (log.isWarnEnabled()) {
                log.warn("No servers available for service: " + this.serviceId);
            }

            return new EmptyResponse();
        } else {
            // 随机获取
            int index = ThreadLocalRandom.current().nextInt(instances.size());
            ServiceInstance instance = (ServiceInstance)instances.get(index);
            return new DefaultResponse(instance);
        }
    }

Spring Cloud LoadBalancer 中缓存机制

尽管关闭缓存对于开发和测试很有用,但是在生产环境上,它的效率是要远低于开启缓存,所以在生产环境上始终都要开启缓存。

Spring Cloud LoadBalancer 中获取服务实例有两种方式:

  • 实时获取:每次都从注册中心得到最新的健康实例(效果好,开销大)
  • 缓存服务列表:每次得到服务列表之后,缓存一段时间(既保证性能,也能保证一定的及时性)

缓存配置:

  • 缓存的过期时间为 35s;
  • 缓存保存个数为 256 个。
spring:
  cloud:
    loadbalancer:
      cache:
        ttl: 35s  # 过期时间
        capacity: 1024  # 设置缓存个数
spring:
  cloud:
    loadbalancer:
      cache:
        enabled: false  # 关闭缓存

https://blog.csdn.net/xaiobit_hl/article/details/134283093

https://blog.csdn.net/weixin_73000974/article/details/135901495

Last Updated:
Contributors: 拔土豆的程序员