令牌桶限流通过信号量实现

场景

1.为了防止第三方无节制的调用打垮我们的系统,需要对重要的请求进行限流。
2.服务方对我们调用的接口有每分钟限流

场景1通常已经有比较成熟的框架支持,只需要简单的配置即可,即可在系统中引入限流机制如alibaba sentinel,spring clound hystrix

场景2服务方对我们限流,为了能正确获得服务结果,我们也需要对我们的请求进行限流发起。

常见的几种限流方案

计数限流、固定窗口、滑动窗口、漏桶算法、令牌桶

最简单的方案

非上面限流算法,既然对方限流我们,那我们只要一直请求,请求结果如果是限制请求,那么我们sleep一段时间,再继续发起请求

public class WeTask{

    public static void main(String[] args) {
        // 伪代码
        task(1);
    }

    public Static void  task(int para) {
        
        Boolean res = getResponse();
        if (!res) {
           //限流了
            Thread.sleep(1000);
            // 继续发起上次请求
            task(para);
        }
        // 处理结果
        dosomething()
    }
}

令牌桶通过信号量实现

由于是我们限制自己的发起请求,对方限制我们的结果,因此根据对方给的限制每分钟300个请求的限制,使用令牌桶,来控制我们的请求。

代码里省略了很多细节,主要为了理解信号量怎么实现令牌桶,通过acquire、release两个方法实现往桶里取、放。

public class WeTask{
        
        @autowire
        Semaphore apiSemaphore;

         @Bean(name = "apiSemaphore")
         public Semaphore apiSemaphore() {
         Semaphore apiSemaphore = new Semaphore(40, true);
         scheduledThreadPoolExecutor.scheduleAtFixedRate(() -> {
            try {
                // 每10s往桶里放允许的请求数
                log.info("release ...40");
                apiSemaphore.release(40);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
         }, -1, 10, TimeUnit.SECONDS);
         return apiSemaphore;
     }


     public static void main(String[] args) {
        // 伪代码
        task(1);
    }

    public Static void  task(int para) {
        apiSemaphore.acquire();
        Boolean res = getResponse();
        //伪代码 还要再次判断可能限流(不信任原则,对方可能会调整限流量)
        // 处理结果
        dosomething()
    }

}

涉及到的API

scheduledThreadPoolExecutor: 定时任务线程池和Timer类似,但是比他强大,支持多线程的定时任务

Semaphore: 信号量,内部类继承实现AQS,支持公平、非公平锁

其他相关知识点参考之前的:栅栏和闭锁

https://blog.csdn.net/u013565163/article/details/87310700

你可能感兴趣的:(java,开发语言)