MaSks要加油丫
发布于 2024-02-17 / 47 阅读
0
0

单机下服务限流

单机服务限流是指在单个服务器实例中,通过技术手段限制单位时间内的请求量,防止服务因过载而崩溃。它就像给单台机器装了一个 "流量阀门",只允许指定数量的请求通过。单机限流可以直接使用 Google Guava 自带的限流工具类 RateLimiter

RateLimiter可以从非阻塞式限流,阻塞定时式限流,阻塞限流三种方式分析:

不管是什么方式,引入依赖都是第一步。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.0.1-jre</version>
</dependency>

一、非阻塞式限流

核心特点当请求量超过限制时,直接拒绝多余的请求,不等待。也可以这么形象的理解为,游乐园的某个项目,每小时只能容纳 100 人,满了就直接告诉后面的人 "今日名额已满",不会让他们排队。

 @RestController
 public class RateLimitController {

    //允许每秒钟发放两个通行证
    RateLimiter rateLimiter = RateLimiter.create(2.0);

    //非阻塞限流
    @GetMapping("/tryAcquire")
    public String tryAcquire(Integer count){

        if(rateLimiter.tryAcquire(count))   //当前请求每秒钟消耗count个令牌 如果count==1说明每秒钟可以通过两个请求
            {
            System.out.println("success ,rate is " + rateLimiter.getRate());
            return "success";
        }else{
            System.out.println("fail ,rate is " + rateLimiter.getRate());
            return "fail";
        }
    }
}

二、阻塞定时限流

核心特点:当请求量超过限制时,让请求等待一段时间,如果在规定时间内拿到 "名额" 就处理,否则拒绝。就好像餐厅等位,告知顾客 "最多等 10 分钟",10 分钟内有空位就安排入座,否则建议顾客离开。

     @GetMapping("/tryAcquireWithTimeOut")
     public String tryAcquireWithTimeOut(Integer count , Integer timeout){

        if(rateLimiter.tryAcquire(count,timeout, TimeUnit.SECONDS))   //当前请求每秒钟消耗count个令牌 如果count==1说明每秒钟可以通过两个请求
        {
            System.out.println("success ,rate is " + rateLimiter.getRate());
            return "success";
        }else{
            System.out.println("fail ,rate is " + rateLimiter.getRate());
            return "fail";
        }
    }

三、阻塞式限流

核心特点:当请求量超过限制时,让多余的请求等待,直到有 "名额" 再处理,不会直接拒绝。就像超市收银台,一次只能处理 1 个顾客,如果后面有人来,就必须排队等待,直到前面的人处理完。

    @GetMapping("/acquire")
    public String acquire(Integer count){

        rateLimiter.acquire(count);
        System.out.println("success ,rate is " + rateLimiter.getRate());
        return "success";
    }

需要注意的是,以上的方案都不是真正的分布式限流,仅仅是局限于当前服务器上,只能保障单个实例的请求处理,无法解决分布式集群的 “全局流量管控” 问题。若要在分布式场景下实现真正的限流,必须跳出 “本地状态” 的局限,通过中间件共享全局限流状态(如用 Redis 统计全集群请求量、用分布式 Semaphore 控制全局资源),才能避免 “单机合规但集群过载” 的风险。


评论