MST

星途 面试题库

面试题:Spring Cloud中如何实现精确的限流策略以保障微服务稳定性

假设你负责一个高并发的微服务项目,使用Spring Cloud框架,描述如何实现基于令牌桶算法或者漏桶算法的精确限流策略,确保服务在高负载下的稳定性,同时要提及如何处理限流后的请求。
26.4万 热度难度
后端开发微服务架构

知识考点

AI 面试

面试题答案

一键面试

基于令牌桶算法实现精确限流策略

  1. 引入依赖:在pom.xml中添加相关限流依赖,如guava库,它提供了令牌桶算法的实现。
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.1-jre</version>
</dependency>
  1. 创建令牌桶:在Spring配置类中,创建令牌桶实例,设置每秒生成令牌数(限流速率)和令牌桶容量。
import com.google.common.util.concurrent.RateLimiter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RateLimiterConfig {

    @Bean
    public RateLimiter rateLimiter() {
        // 每秒生成2个令牌,桶容量为10
        return RateLimiter.create(2); 
    }
}
  1. 在微服务方法中使用令牌桶限流:在需要限流的微服务方法调用前,尝试获取令牌。如果获取成功,则继续处理请求;否则,限流处理。
import com.google.common.util.concurrent.RateLimiter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @Autowired
    private RateLimiter rateLimiter;

    @GetMapping("/myEndpoint")
    public String myEndpoint() {
        if (rateLimiter.tryAcquire()) {
            // 处理请求
            return "Request processed successfully";
        } else {
            // 限流处理
            return "Too many requests, please try again later";
        }
    }
}

基于漏桶算法实现精确限流策略

  1. 自定义漏桶算法实现:实现一个简单的漏桶算法,维护一个队列和固定的流出速率。
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

public class LeakyBucket {
    private final long capacity;
    private final long rate;
    private long lastLeakTime;
    private long water;
    private final LinkedBlockingQueue<Runnable> requestQueue = new LinkedBlockingQueue<>();

    public LeakyBucket(long capacity, long rate) {
        this.capacity = capacity;
        this.rate = rate;
        this.lastLeakTime = System.nanoTime();
        this.water = 0;
        startLeak();
    }

    private void startLeak() {
        Thread leakThread = new Thread(() -> {
            while (true) {
                try {
                    long now = System.nanoTime();
                    long elapsedTime = now - lastLeakTime;
                    long leakedWater = elapsedTime * rate / TimeUnit.SECONDS.toNanos(1);
                    water = Math.max(0, water - leakedWater);
                    lastLeakTime = now;

                    Runnable request = requestQueue.poll();
                    if (request != null && water < capacity) {
                        water++;
                        request.run();
                    }

                    TimeUnit.MILLISECONDS.sleep(10);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });
        leakThread.setDaemon(true);
        leakThread.start();
    }

    public boolean tryEnqueue(Runnable request) {
        if (water >= capacity) {
            return false;
        }
        return requestQueue.offer(request);
    }
}
  1. 在Spring中使用漏桶算法:在Spring配置类中创建漏桶实例,并在控制器中使用。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class LeakyBucketConfig {

    @Bean
    public LeakyBucket leakyBucket() {
        // 桶容量为10,每秒处理2个请求
        return new LeakyBucket(10, 2); 
    }
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @Autowired
    private LeakyBucket leakyBucket;

    @GetMapping("/myEndpoint")
    public String myEndpoint() {
        if (leakyBucket.tryEnqueue(() -> {
            // 处理请求逻辑
        })) {
            return "Request processed successfully";
        } else {
            return "Too many requests, please try again later";
        }
    }
}

处理限流后的请求

  1. 返回友好提示:如上述代码示例,直接返回类似“Too many requests, please try again later”的提示信息,告知用户请求过多,请稍后重试。
  2. 记录日志:使用日志框架记录限流的请求信息,包括请求来源、时间等,方便后续分析高负载情况和优化系统。
  3. 异步处理:将限流后的请求放入队列,通过异步线程或消息队列(如RabbitMQ、Kafka)进行处理,在系统负载降低时逐步处理这些请求。
  4. 熔断与降级:结合熔断机制(如Hystrix),当限流频繁发生时,触发熔断,直接返回降级处理结果,避免大量无效请求对系统造成更大压力。