MST

星途 面试题库

面试题:微服务架构中Spring Cloud Gateway智能路由的负载均衡策略

Spring Cloud Gateway支持多种负载均衡策略,如轮询、随机等。假设你在一个高并发的微服务场景下,用户服务有多个实例,你认为哪种负载均衡策略更适合,为什么?并且如何在Spring Cloud Gateway中配置你所选择的负载均衡策略?
29.3万 热度难度
后端开发微服务架构

知识考点

AI 面试

面试题答案

一键面试

更适合的负载均衡策略及原因

在高并发的微服务场景下,加权轮询负载均衡策略相对更适合。原因如下:

  • 均匀分配请求:轮询策略可以将请求均匀地分配到各个实例上,避免某个实例过度负载,在一定程度上保证各实例资源利用的均衡性。但它没有考虑实例的性能差异。
  • 考虑实例性能:加权轮询策略在轮询的基础上,根据实例的性能为每个实例分配不同的权重。性能好的实例权重高,会被分配到更多的请求;性能差的实例权重低,接收的请求相对较少。这样既能充分利用高性能实例的资源,又不会让低性能实例过载,更适合高并发场景下不同性能的实例共同处理请求的情况。

在Spring Cloud Gateway中配置加权轮询负载均衡策略

  1. 引入依赖:如果使用Spring Cloud Alibaba Nacos作为服务注册中心(Nacos自带负载均衡功能支持加权轮询等策略),在pom.xml中添加Nacos客户端和负载均衡相关依赖:
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
  1. 配置Nacos服务发现:在application.yml中配置Nacos服务发现相关参数:
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # Nacos服务器地址
  1. 配置负载均衡策略:在application.yml中配置使用加权轮询负载均衡策略,以访问名为user-service的服务为例:
spring:
  cloud:
    loadbalancer:
      loadbalancers:
        user-service:
          ribbon:
            NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule

这里NacosRule就是Nacos提供的支持加权轮询的负载均衡规则。如果不使用Nacos,也可以通过自定义负载均衡规则来实现加权轮询策略,具体步骤如下:

  1. 创建自定义负载均衡规则类:实现IRule接口,在choose方法中实现加权轮询逻辑。例如:
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.Server;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class WeightedRoundRobinRule implements IRule {
    private ILoadBalancer lb;
    private AtomicInteger nextServerCyclicCounter;

    public WeightedRoundRobinRule() {
        nextServerCyclicCounter = new AtomicInteger(0);
    }

    @Override
    public Server choose(Object key) {
        if (lb == null) {
            return null;
        }
        List<Server> upList = lb.getReachableServers();
        List<Server> allList = lb.getAllServers();

        int serverCount = upList.size();
        if (serverCount == 0) {
            return null;
        }

        int totalWeight = 0;
        for (Server server : upList) {
            // 假设服务器实例有getWeight方法获取权重
            int weight = server.getWeight();
            totalWeight += weight;
        }

        int currentIndex = incrementAndGetModulo(serverCount);
        int weightIndex = currentIndex;
        int currentWeight = 0;
        do {
            Server server = upList.get(weightIndex);
            // 假设服务器实例有getWeight方法获取权重
            currentWeight += server.getWeight();
            if (currentWeight * serverCount >= totalWeight * (currentIndex + 1)) {
                return server;
            }
            weightIndex = (weightIndex + 1) % serverCount;
        } while (weightIndex != currentIndex);

        return upList.get(currentIndex);
    }

    private int incrementAndGetModulo(int modulo) {
        for (; ; ) {
            int current = nextServerCyclicCounter.get();
            int next = (current + 1) % modulo;
            if (nextServerCyclicCounter.compareAndSet(current, next))
                return next;
        }
    }

    @Override
    public void setLoadBalancer(ILoadBalancer lb) {
        this.lb = lb;
    }

    @Override
    public ILoadBalancer getLoadBalancer() {
        return lb;
    }
}
  1. 配置自定义负载均衡规则:在配置类中注入自定义的负载均衡规则:
import com.netflix.loadbalancer.IRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class LoadBalancerConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Bean
    public IRule ribbonRule() {
        return new WeightedRoundRobinRule();
    }
}

这样就可以在Spring Cloud Gateway中使用自定义的加权轮询负载均衡策略。