2.算法-手寫滑動窗口限流

限流

爲啥要限流,大多數情況是服務器資源不足,短時間內大量流量請求到服務器,限流會有部分流量正常返回,部分流量異常,好過服務器宕機,所有流量異常返回的情況。

在代碼世界上,限流有兩種比較常見的算法:

1.令牌桶算法
2.漏桶算法

還有一種是滑動窗口限流,最早接觸滑動窗口是TCP協議

滑動窗口

在這裏插入圖片描述

手寫滑動窗口限流

設計思路:

Dqueue記錄每次請求時間戳,每次計算時間窗口是否超過設定值,沒有超出計數,超出清空Dqueue,計數歸零,重新計算窗口。

簡單的設計,單元測試可用,歡迎高手交流,此算法不推薦生產環境使用。
建議使用guvav 中限流算法

手寫滑動窗口限流

public class slidingWindows {
    
    /**
     * 時間窗口
     **/
    private Long window;
    /**
     * 窗口的size 用於計算總的流量上限
     **/
    private Integer size = 2000;

    /**
     * 原子計數
     **/
    private AtomicInteger count;

    /**
     * Deque雙隊列
     */
    private Deque<Long> timequeue;


    public slidingWindows(Long windowCount) {
        this.window = windowCount;
        this.timequeue = new ConcurrentLinkedDeque<>();
        this.count = new AtomicInteger(0);
        timequeue.addFirst(System.currentTimeMillis());
    }

    /**
     * 流量限制
     **/
    public Boolean tryout() {
        Long now = System.currentTimeMillis();
        if ((now - timequeue.peekLast()) > window) {
            timequeue.clear();
            timequeue.addFirst(now);
            count.set(0);
        } else {
            if (count.addAndGet(1) < size) {
                timequeue.add(now);
                System.out.println("time: " + count.get());
                return true;
            }

        }
        return Boolean.FALSE;
    }

    public static void main(String[] args) {
        slidingWindows ms = new slidingWindows(1000L);

        // 創建固定大小的線程池
        ExecutorService threadPool = Executors.newFixedThreadPool(100);    // 創建線程池內最大num個線程同時執行

        // 創建線程
        // 開始全部將線程加入線程池
        // 執行num個線程同時執行
        for (int i = 0; i < 100000; i++) {
            Runnable r = new Runnable() {
                public void run() {
                    try {
                        sleep(10);
                        System.out.println(ms.tryout());
                        Thread t = Thread.currentThread();
                        /*System.out.println(t.getName());
                        System.out.println(t.getName());*/
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            };
            threadPool.execute(r);
        }

        threadPool.shutdown();

    }
}

應用實踐

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章