限流策略简述

限流策略指的是一种通过限制系统请求或者流量数量的方法,以防止系统的过载或崩溃。常见的限流策略包括:

  1. 计数器限流:设置一个阈值,每次请求都将计数器加一,当计数器达到阈值时,拒绝后续请求或者将请求放入队列中,等待处理。

  2. 令牌桶限流:通过维护一个令牌桶,限制系统的请求流量。令牌桶中存放着一定数量的令牌,每次请求需要获取一个令牌,当令牌桶中的令牌用尽时,拒绝后续请求或将请求放入队列中等待处理。同时,每隔一段时间会往令牌桶中放入一定数量的令牌。

  3. 漏桶限流:类似于令牌桶限流,不同的是漏桶不是令牌,而是通过固定速率将请求处理,当请求流量超过漏桶处理速率时,多余的请求将被拒绝或者放入队列中等待处理。

  4. 基于时间窗口的限流:通过设置一个时间窗口,例如每秒钟只允许处理一定数量的请求,当请求超过阈值时,拒绝后续请求或将请求放入队列中等待处理。时间窗口的长度和阈值可以根据实际情况进行调整。

下面通过代码demo展示基于时间窗口限流策略:单位时间内限定访问数量


/*
基于时间窗口的限流算法是一种常见的限流技术,
它通过限制在指定时间窗口内的请求数量来控制系统的并发请求量。
该算法可以灵活地控制请求的速率,通常用于对接口请求进行限流。
*/
public class TimeWindowLimiter {

        private int limit; // 时间窗口内最大请求数量
        private long interval; // 时间窗口大小,单位毫秒
        private Queue queue = new LinkedList<>(); // 时间窗口请求时间队列

        public TimeWindowLimiter(int limit, long interval) {
            this.limit = limit;
            this.interval = interval;
        }
        // 判断当前是否允许处理请求
        public synchronized boolean allow() {
            long now = System.currentTimeMillis();
            // 移除超时的请求
            while (!queue.isEmpty() && now - queue.peek() >= interval) {
                queue.poll();  //用于从队列中删除并返回头部元素
            }
            // 如果请求数量超过限制,则不允许处理请求
            if (queue.size() >= limit) {
                return false;
            }
            // 记录当前请求时间,并允许处理请求
            queue.offer(now);
            return true;
        }
}

单元测试:

public class FilterTest {
    @Test
    public void Threadtest(){
        int threadCount = 2; // 线程数量
        int requestCount = 10; // 每个线程发起的请求数量
        int limit = 10; // 时间窗口内最大请求数量
        long interval = 10000; // 时间窗口大小,单位毫秒
        TimeWindowLimiter limiter = new TimeWindowLimiter(limit, interval);
        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);

        for (int i = 0; i < threadCount; i++) {
            executorService.execute(() -> {
                for (int j = 0; j < requestCount; j++) {
                    if (limiter.allow()) {
                        System.out.println("处理请求 " + Thread.currentThread().getName() + "-" + j);
                    } else {
                        System.out.println("限流请求 " + Thread.currentThread().getName() + "-" + j);
                    }
                }
            });
        }
        executorService.shutdown();
    }
}

系统的并发数访问限制---基于令牌桶算法

令牌桶算法的实现,通过维护一个固定容量的令牌桶来控制请求的处理速率。每个请求需要获取一个令牌才能被处理,如果令牌桶中没有足够的令牌,则需要等待一定的时间才能获取到令牌。可以通过调整令牌桶的容量和令牌的生成速率来控制请求的处理速率。

import com.google.common.util.concurrent.RateLimiter;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*系统的并发限制*/
public class RateLimiterTest {
    private static final int THREAD_NUM = 200;
        public static void main(String[] args) throws InterruptedException {
            RateLimiter rateLimiter = RateLimiter.create(10);  //并发线程要求为10,即每秒生成10个令牌
            // 创建一个线程池,包含固定数量的线程
            ExecutorService executor = Executors.newFixedThreadPool(THREAD_NUM);
            CountDownLatch latch = new CountDownLatch(THREAD_NUM);
            for (int i = 0; i {
                    try {
                        double waitTime = rateLimiter.acquire(); //模拟每个线程处理业务,获取可用令牌所需的等待时间           
                        System.out.println("请求" + Thread.currentThread().getName() + "处理完毕,等待时间:" + waitTime + "秒");
                    }finally {
                        latch.countDown();
                    }
                });
            }

            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("All threads finished");
            executor.shutdown();

        }


}

RateLimiter.create(10)是Guava提供的一种创建限流器的方式,其中10表示每秒最多处理10个请求,可以根据实际需求进行调整。该方式创建的限流器是基于令牌桶算法的实现。

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