日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

為什么要限流?常見的限流算法有哪些?

來源: 責編: 時間:2024-06-05 17:40:05 247觀看
導讀實際開發中,當業務流量過大時,為了保護下游服務,我們通常會做一些預防性的工作,今天我們就一起來聊聊限流!一、為什么需要限流?在實際應用中,每個系統或者服務都有其處理能力的極限(瓶頸),即便是微服務中有集群和分布式的夾持,也

實際開發中,當業務流量過大時,為了保護下游服務,我們通常會做一些預防性的工作,今天我們就一起來聊聊限流!4AF28資訊網——每日最新資訊28at.com

4AF28資訊網——每日最新資訊28at.com

一、為什么需要限流?

在實際應用中,每個系統或者服務都有其處理能力的極限(瓶頸),即便是微服務中有集群和分布式的夾持,也不能保證系統能應對任何大小的流量,因此,系統為了自保,需要對處理能力范圍以外的流量進行“特殊照顧”(比如,丟棄請求或者延遲處理),從而避免系統卡死、崩潰或不可用等情況,保證系統整體服務可用。4AF28資訊網——每日最新資訊28at.com

二、限流算法

1.令牌桶算法

令牌桶算法(Token Bucket Algorithm)是計算機網絡和電信領域中常用的一種簡單方法,用于流量整形和速率限制。它旨在控制系統在某個時間段內可以發送或接收的數據量,確保流量符合指定的速率。4AF28資訊網——每日最新資訊28at.com

令牌桶算法的核心思路:系統按照固定速度往桶里加入令牌,如果桶滿則停止添加。當有請求到來時,會嘗試從桶里拿走一個令牌,取到令牌才能繼續進行請求處理,沒有令牌就拒絕服務。示意圖如下:4AF28資訊網——每日最新資訊28at.com

4AF28資訊網——每日最新資訊28at.com

令牌桶法的幾個特點:4AF28資訊網——每日最新資訊28at.com

  • 令牌桶容量固定,即系統的處理能力閾值
  • 令牌放入桶內的速度固定
  • 令牌從桶內拿出的速度根據實際請求量而定,每個請求對應一個令牌
  • 當桶內沒有令牌時,請求進入等待或者被拒絕

令牌桶算法主要用于應對突發流量的場景,在 Java語言中使用最多的是 Google的 Guava RateLimiter,下面舉幾個例子來說明它是如何應對突發流量:4AF28資訊網——每日最新資訊28at.com

示例14AF28資訊網——每日最新資訊28at.com

import java.util.concurrent.TimeUnit;public class RateLimit {  public static void main(String[] args) {    RateLimiter limiter = RateLimiter.create(5); // 每秒創建5個令牌    System.out.println("acquire(5), wait " + limiter.acquire(5) + " s"); // 全部取走 5個令牌    System.out.println("acquire(1), wait " + limiter.acquire(1) + " s");// 獲取1個令牌    boolean result = limiter.tryAcquire(1, 0, TimeUnit.SECONDS); // 嘗試獲取1個令牌,獲取不到則直接返回    System.out.println("tryAcquire(1), result: " + result);  }}

示例代碼運行結果如下:4AF28資訊網——每日最新資訊28at.com

acquire(5), wait 0.0 sacquire(1), wait 0.971544 stryAcquire(1), result: false

桶中共有 5個令牌,acquire(5)返回0 代表令牌充足無需等待,當桶中令牌不足,acquire(1)等待一段時間才獲取到,當令牌不足時,tryAcquire(1)不等待直接返回。4AF28資訊網——每日最新資訊28at.com

示例24AF28資訊網——每日最新資訊28at.com

import com.google.common.util.concurrent.RateLimiter;public class RateLimit {    public static void main(String[] args) {        RateLimiter limiter = RateLimiter.create(5);        System.out.println("acquire(10), wait " + limiter.acquire(10) + " s");        System.out.println("acquire(1), wait " + limiter.acquire(1) + " s");    }}

示例代碼運行結果如下:4AF28資訊網——每日最新資訊28at.com

acquire(10), wait 0.0 sacquire(1), wait 1.974268 s

桶中共有 5個令牌,acquire(10)返回0,和示例似乎有點沖突,其實,這里返回0 代表應對了突發流量,但是 acquire(1)4AF28資訊網——每日最新資訊28at.com

卻等待了 1.974268秒,這代表 acquire(1)的等待是時間包含了應對突然流量多出來的 5個請求,即 1.974268 = 1 + 0.974268。4AF28資訊網——每日最新資訊28at.com

為了更好的驗證示例2的猜想,我們看示例3:4AF28資訊網——每日最新資訊28at.com

示例34AF28資訊網——每日最新資訊28at.com

import com.google.common.util.concurrent.RateLimiter;import java.util.concurrent.TimeUnit;public class RateLimit {    public static void main(String[] args) throws InterruptedException {        RateLimiter limiter = RateLimiter.create(5);        System.out.println("acquire(5), wait " + limiter.acquire(5) + " s");        TimeUnit.SECONDS.sleep(1);        System.out.println("acquire(5), wait " + limiter.acquire(5) + " s");        System.out.println("acquire(1), wait " + limiter.acquire(1) + " s");    }}

示例代碼運行結果如下:4AF28資訊網——每日最新資訊28at.com

acquire(5), wait 0.0 sacquire(5), wait 0.0 sacquire(1), wait 0.966104 s

桶中共有 5個令牌,acquire(5)返回0 代表令牌充足無需等待,接著睡眠 1s,這樣系統又可以增加5個令牌,因此,再次 acquire(5)令牌充足返回0 無需等待,acquire(1)需要等待一段時間才能獲取令牌。4AF28資訊網——每日最新資訊28at.com

2.漏桶算法

漏桶算法(Leaky Bucket Algorithm)的核心思路是:水(請求)進入固定容量的漏桶,漏桶的水以固定的速度流出,當水流入漏桶的速度過大導致漏桶滿而直接溢出,然后拒絕請求。示意圖如下:4AF28資訊網——每日最新資訊28at.com

4AF28資訊網——每日最新資訊28at.com

下面為一個 Java版本的漏桶算法示例:4AF28資訊網——每日最新資訊28at.com

import java.util.concurrent.*;public class LeakyBucket {    private final int capacity; // 桶的容量    private final int rate;     // 出水速率    private int water;          // 漏斗中的水量    private long lastLeakTime;  // 上一次漏水的時間    public LeakyBucket(int capacity, int rate) {        this.capacity = capacity;        this.rate = rate;        this.water = 0;        this.lastLeakTime = System.currentTimeMillis();    }    public synchronized boolean allowRequest(int tokens) {        leak(); // 漏水        if (water + tokens <= capacity) {            water += tokens; // 漏斗容量未滿,可以加水            return true;        } else {            return false; // 漏斗容量已滿,無法加水        }    }    private void leak() {        long currentTime = System.currentTimeMillis();        long timeElapsed = currentTime - lastLeakTime;        int waterToLeak = (int) (timeElapsed * rate / 1000); // 計算經過的時間內應該漏掉的水量        water = Math.max(0, water - waterToLeak); // 漏水        lastLeakTime = currentTime; // 更新上一次漏水時間    }    public static void main(String[] args) {        LeakyBucket bucket = new LeakyBucket(10, 2); // 容量為10,速率為2令牌/秒        int[] packets = {2, 3, 1, 5, 2, 10}; // 要發送的數據包大小        for (int packet : packets) {            if (bucket.allowRequest(packet)) {                System.out.println("發送 " + packet + " 字節的數據包");            } else {                System.out.println("漏桶已滿,無法發送數據包");            }            try {                TimeUnit.SECONDS.sleep(1); // 模擬發送間隔            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

漏桶算法的幾個特點:4AF28資訊網——每日最新資訊28at.com

  • 漏桶容量固定
  • 流入(請求)速度隨意
  • 流出(處理請求)速度固定
  • 桶滿則溢出,即拒絕新請求(限流)

3.計數器算法

計數器是最簡單的限流方式,主要用來限制總并發數,主要通過一個支持原子操作的計數器來累計 1秒內的請求次數,當 秒內計數達到限流閾值時觸發拒絕策略。每過 1秒,計數器重置為 0開始重新計數。比如數據庫連接池大小、線程池大小、程序訪問并發數等都是使用計數器算法。4AF28資訊網——每日最新資訊28at.com

如下代碼就是一個Java版本的計數器算法示例,通過一個原子計算器 AtomicInteger來記錄總數,如果請求數大于總數就拒絕請求,否則正常處理請求:4AF28資訊網——每日最新資訊28at.com

import java.util.concurrent.atomic.AtomicInteger;public class CounterRateLimiter {    private final int limit;          // 限流閾值    private final long windowSizeMs;  // 時間窗口大小(毫秒)    private AtomicInteger counter;    // 請求計數器    private long lastResetTime;       // 上次重置計數器的時間    public CounterRateLimiter(int limit, long windowSizeMs) {        this.limit = limit;        this.windowSizeMs = windowSizeMs;        this.counter = new AtomicInteger(0);        this.lastResetTime = System.currentTimeMillis();    }    public boolean allowRequest() {        long currentTime = System.currentTimeMillis();        // 如果當前時間超出了時間窗口,重置計數器        if (currentTime - lastResetTime > windowSizeMs) {            counter.set(0);            lastResetTime = currentTime;        }        // 檢查計數器是否超過了限流閾值        return counter.incrementAndGet() <= limit;    }    public static void main(String[] args) {        CounterRateLimiter rateLimiter = new CounterRateLimiter(3, 1000); // 每秒最多處理3個請求        for (int i = 0; i < 10; i++) {            if (rateLimiter.allowRequest()) {                System.out.println("允許請求 " + (i + 1));            } else {                System.out.println("限流,拒絕請求 " + (i + 1));            }            try {                Thread.sleep(200); // 模擬請求間隔            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

4.滑動窗口算法

滑動窗口算法是一種常用于限流和統計的算法。它基于一個固定大小的時間窗口,在這個時間窗口內統計請求的數量,并根據設定的閾值來控制流量。比如,TCP協議就使用了該算法4AF28資訊網——每日最新資訊28at.com

以下是一個簡單的 Java 示例實現滑動窗口算法:4AF28資訊網——每日最新資訊28at.com

import java.util.concurrent.atomic.AtomicInteger;public class SlidingWindowRateLimiter {    private final int limit;          // 限流閾值    private final long windowSizeMs;  // 時間窗口大小(毫秒)    private final AtomicInteger[] window;  // 滑動窗口    private long lastUpdateTime;      // 上次更新窗口的時間    private int pointer;              // 指向當前時間窗口的指針    public SlidingWindowRateLimiter(int limit, long windowSizeMs, int granularity) {        this.limit = limit;        this.windowSizeMs = windowSizeMs;        this.window = new AtomicInteger[granularity];        for (int i = 0; i < granularity; i++) {            window[i] = new AtomicInteger(0);        }        this.lastUpdateTime = System.currentTimeMillis();        this.pointer = 0;    }    public synchronized boolean allowRequest() {        long currentTime = System.currentTimeMillis();        // 計算時間窗口的起始位置        long windowStart = currentTime - windowSizeMs + 1;        // 更新窗口中過期的計數器        while (lastUpdateTime < windowStart) {            lastUpdateTime++;            window[pointer].set(0);            pointer = (pointer + 1) % window.length;        }        // 檢查窗口內的總計數是否超過限流閾值        int totalRequests = 0;        for (AtomicInteger counter : window) {            totalRequests += counter.get();        }        if (totalRequests >= limit) {            return false; // 超過限流閾值,拒絕請求        } else {            window[pointer].incrementAndGet(); // 記錄新的請求            return true; // 允許請求        }    }    public static void main(String[] args) {        SlidingWindowRateLimiter rateLimiter = new SlidingWindowRateLimiter(10, 1000, 10); // 每秒最多處理10個請求        for (int i = 0; i < 20; i++) {            if (rateLimiter.allowRequest()) {                System.out.println("允許請求 " + (i + 1));            } else {                System.out.println("限流,拒絕請求 " + (i + 1));            }            try {                Thread.sleep(100); // 模擬請求間隔            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

5.Redis + Lua分布式限流

Redis + Lua屬于分布式環境下的限流方案,主要利用的是Lua在 Redis中運行能保證原子性。如下示例為一個簡單的Lua限流腳本:4AF28資訊網——每日最新資訊28at.com

local key = KEYS[1]local limit = tonumber(ARGV[1])local current = tonumber(redis.call('get', key) or "0")if current + 1 > limit then    return 0else    redis.call("INCRBY", key, 1)    redis.call("EXPIRE", key, 1)    return 1end

腳本解釋:4AF28資訊網——每日最新資訊28at.com

  • KEYS[1]:限流的鍵名,注意,在Lua中,下角標是從 1開始
  • ARGV[1]:限流的最大值
  • redis.call(‘get’, key):獲取當前限流計數。
  • redis.call(‘INCRBY’, key, 1):增加限流計數。
  • redis.call(‘EXPIRE’, key, 1):設置鍵的過期時間為 1 秒。

6.三方限流工具

當我們自己無法實現比較好的限流方案時,成熟的三方框架就是我們比較好的選擇,下面列出兩個 Java語言比較優秀的框架。4AF28資訊網——每日最新資訊28at.com

(1) resilience4j4AF28資訊網——每日最新資訊28at.com

resilience4j 是一個輕量級的容錯庫,提供了限流、熔斷、重試等功能。限流模塊 RateLimiter 提供了靈活的限流配置,其優點如下:4AF28資訊網——每日最新資訊28at.com

  • 集成了多種容錯機制
  • 支持注解方式配置
  • 易于與 Spring Boot集成

(2) Sentinel4AF28資訊網——每日最新資訊28at.com

Sentinel 是阿里巴巴開源的一個功能全面的流量防護框架,提供限流、熔斷、系統負載保護等多種功能。其優點如下:4AF28資訊網——每日最新資訊28at.com

  • 功能全面,適用于多種場景
  • 強大的監控和控制臺
  • 與 Spring Cloud 深度集成

三、總結

本文講述了以下幾種限流方式:4AF28資訊網——每日最新資訊28at.com

  • 計數器
  • 滑動窗口
  • 漏桶
  • 令牌桶
  • Redis + Lua 分布式限流
  • 三方限流工具

上面的限流方式,主要是針對服務器進行限流,除此之外,我們也可以對客戶端進行限流, 比如驗證碼,答題,排隊等方式。4AF28資訊網——每日最新資訊28at.com

另外,我們也會在一些中間件上進行限流,比如Apache、Tomcat、Nginx等。4AF28資訊網——每日最新資訊28at.com

在實際的開發中,限流場景略有差異,限流的維度也不一樣,比如,有的場景需要根據請求的 URL來限流,有的會對 IP地址進行限流、另外,設備ID、用戶ID 也是限流常用的維度,因此,我們需要結合真實業務場景靈活的使用限流方案。4AF28資訊網——每日最新資訊28at.com

本文鏈接:http://m.www897cc.com/showinfo-26-92106-0.html為什么要限流?常見的限流算法有哪些?

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 玩轉Redis!非常強大的Redisson分布式集合,少寫60%代碼

下一篇: .NET 中的數據交互:生成和讀取YAML文件

標簽:
  • 熱門焦點
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
欧美午夜电影在线观看| 久久精品道一区二区三区| 亚洲丶国产丶欧美一区二区三区 | 好看的av在线不卡观看| 伊大人香蕉综合8在线视| 亚洲国产mv| 99re热这里只有精品免费视频| 中文一区在线| 久久久噜噜噜久久中文字免| 欧美高清视频www夜色资源网| 欧美日韩精品欧美日韩精品一| 国产精品一区视频网站| 夜夜嗨av色综合久久久综合网| 在线亚洲欧美专区二区| 久久精品30| 欧美精品亚洲| 国产日韩在线不卡| 亚洲精品久久久久久一区二区 | 久久久777| 国产欧美高清| 亚洲国内在线| 亚洲欧美一区二区原创| 免费久久99精品国产自| 国产精品国产三级国产aⅴ9色| 狠狠色狠狠色综合系列| 日韩一二在线观看| 久久黄色小说| 欧美色视频一区| 在线免费观看视频一区| 亚洲自啪免费| 欧美激情按摩在线| 国语自产偷拍精品视频偷| 夜夜嗨av一区二区三区网页| 久久免费高清| 国产美女精品一区二区三区 | 亚洲欧美日韩一区二区在线| 欧美大片在线看| 国产一区二区激情| 亚洲一级免费视频| 欧美激情五月| 精品成人久久| 欧美一区二区免费视频| 欧美日韩一区二区三区四区在线观看| 国内综合精品午夜久久资源| 亚洲欧美日韩中文视频| 欧美日韩在线不卡| 最新日韩在线| 久久亚洲一区二区三区四区| 国产精品欧美日韩一区二区| 99re热这里只有精品免费视频| 狼人天天伊人久久| 韩日精品视频| 欧美一区二区日韩| 国产精品久久97| 一本色道久久加勒比精品| 欧美成人免费大片| 红桃av永久久久| 久久av一区二区三区| 国产精品日韩久久久| av成人黄色| 欧美激情日韩| 亚洲国产精品激情在线观看| 久久免费视频一区| 国产在线精品成人一区二区三区 | 亚洲美女在线视频| 玖玖精品视频| 激情成人综合网| 久久国产精品久久久久久| 国产精品日本精品| 亚洲视频一二三| 欧美三级在线播放| 99在线精品观看| 欧美日韩国产欧| 日韩一级网站| 欧美另类视频| 日韩亚洲不卡在线| 欧美激情影音先锋| 亚洲日本欧美| 欧美精品一区二区三区蜜臀| 亚洲区一区二| 欧美日韩激情小视频| 99精品国产高清一区二区 | 一区二区三区在线视频免费观看| 久久精视频免费在线久久完整在线看| 国产精品美女xx| 午夜免费日韩视频| 国产日韩在线亚洲字幕中文| 欧美一区二区日韩一区二区| 国产麻豆一精品一av一免费| 欧美亚洲日本网站| 国产在线国偷精品产拍免费yy| 久久精品亚洲一区二区三区浴池| 国内外成人在线视频| 久久精品免费看| 一区在线视频观看| 欧美国产激情| 一区二区电影免费观看| 国产精品久久久一区二区三区| 亚洲欧美日韩视频二区| 国产综合色在线| 女同性一区二区三区人了人一| 亚洲人成7777| 国产精品www.| 性欧美暴力猛交69hd| 狠狠色丁香久久婷婷综合_中| 男女精品网站| 夜夜嗨av一区二区三区四区| 国产精品露脸自拍| 久久精彩视频| 亚洲国产日韩综合一区| 欧美日韩午夜激情| 先锋影音网一区二区| 影音先锋亚洲视频| 欧美国产高潮xxxx1819| 亚洲午夜精品久久久久久浪潮| 国产精品夜夜夜| 久久全球大尺度高清视频| 亚洲老司机av| 国产精品综合久久久| 久久综合影音| 亚洲一区二区三区777| 国产一区二区三区最好精华液| 欧美成人免费在线| 亚洲一级高清| 在线观看不卡| 国产精品久久久久久久久久尿| 久久精品国产精品亚洲| 亚洲精品美女91| 国产欧美一区二区三区久久 | 久久久www免费人成黑人精品 | 亚洲美女视频在线免费观看| 国产精品高清网站| 久久久久久久一区| 一区二区三区四区五区视频| 国产一区二区三区高清播放| 欧美成人午夜激情在线| 亚洲欧美第一页| 亚洲国产中文字幕在线观看| 国产精品免费网站在线观看| 另类综合日韩欧美亚洲| 中文亚洲欧美| 在线观看国产精品淫| 欧美视频在线播放| 久久综合999| 亚洲欧美日韩中文在线制服| 亚洲国产成人av| 国产精品一区二区三区久久| 欧美激情一区二区三区在线视频| 欧美一区二区视频97| 99re热这里只有精品视频| 黑人中文字幕一区二区三区| 欧美三区在线观看| 麻豆av一区二区三区久久| 亚洲性感美女99在线| 亚洲国产精品一区二区第一页| 国产欧美日韩另类视频免费观看| 欧美激情黄色片| 久久久999国产| 亚洲一二三区在线观看| 亚洲福利一区| 国产自产女人91一区在线观看| 欧美三区在线视频| 欧美福利视频在线观看| 久久久久九九九九| 亚洲免费在线观看视频| 日韩一二在线观看| 在线播放亚洲一区| 国产精品一区免费视频| 欧美日韩一区三区四区| 欧美**人妖| 久久天天躁狠狠躁夜夜爽蜜月| 亚洲欧美另类中文字幕| 亚洲欧洲综合另类| 国产真实精品久久二三区| 国产精品人成在线观看免费 | 国产日本欧美在线观看 | 在线看欧美日韩| 国产亚洲福利一区| 国产精品日韩在线| 欧美日韩在线视频一区| 欧美国产精品中文字幕| 久久综合影视| 久久综合九色99| 久久精品在线免费观看| 午夜精品久久久| 亚洲天堂av电影| 一区二区三区精密机械公司 | 久久久国产亚洲精品| 性欧美超级视频| 亚洲欧美一区二区三区久久| 亚洲一区二区三区视频| 一区二区三区毛片| 一本久道综合久久精品| 亚洲免费成人av电影| 亚洲国产高清自拍| 亚洲国产岛国毛片在线| 亚洲电影激情视频网站| 在线观看日韩欧美| 亚洲第一中文字幕| 亚洲二区在线观看| 亚洲激情网站| 亚洲每日更新| 9i看片成人免费高清| 一区二区av在线|