自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一文帶你了解分布式神器-限流器

開發(fā) 架構(gòu)
作為微服務(wù)服務(wù)保證的三大利器,限流、熔斷、降級,了解其大概的大概的含義是非常有必要的,雖然現(xiàn)在有很多封裝好的限流框架,比如Sentinel、Resilience4j等,但技術(shù)是沒有止境的,當你往下探索 時,更多不可思議的知識,后面有機會我們從源碼,更底層來認識這些技術(shù)與設(shè)計思想。

Guava RateLimiter

有沒有搞錯,別人都在提升系統(tǒng)的訪問并發(fā)量,你卻在這搞限制?

我們都知道,服務(wù)器資源是有限的,當把應(yīng)用部署在外網(wǎng)環(huán)境中,所有人都可以訪問你的應(yīng)用,如果訪問人數(shù)上去了,你的服務(wù)器是否能夠支持足夠量的用戶訪問?在系統(tǒng)訪問高峰時期, 僅從代碼層面提供系統(tǒng)并發(fā)量,系統(tǒng)真的就能夠支持突然流量的沖擊?顯然是不可能的,如果誰讓你在不改變硬件配置的情況下,無限制的提高系統(tǒng)性能,你可以說他在白日做夢。

簡介

限流器顧名思義,就是對流量的限制,準確的說應(yīng)該是流量控制,當然并不是無理由的進行流量控制,應(yīng)該是在計算機硬件能夠承載的范圍內(nèi),防止系統(tǒng)突然流量過高導(dǎo)致系統(tǒng)資源耗盡,最終 系統(tǒng)宕機或崩潰,使得服務(wù)器上的應(yīng)用全部掛掉。限流器是在保證應(yīng)用能夠正常提供服務(wù)的前提下,通過流量控制實現(xiàn)對服務(wù)的一種保護手段。

當然流量的閾值到底是多少比較合適,這個可能需要根據(jù)實際硬件配置、系統(tǒng)環(huán)境以前其他相關(guān)參數(shù)經(jīng)過各種測試與驗證才能知道...

本篇文章僅討論限流中相關(guān)的技術(shù),在實際應(yīng)用中使用的限流器,除了包含流量限制的作用,為了提高用戶體驗,還需要對流量超出是,做出對應(yīng)的應(yīng)對策略,比如直接拒絕服務(wù),讓請求進行排隊 ,或者服務(wù)降級都是比較好的處理手段,這樣既能給用戶友好地體驗,又能保證服務(wù)正常。

核心

有幾個核心概念需要先了解到:

  • 限流的目標對象:請求數(shù)量、網(wǎng)絡(luò)流量、用戶訪問次數(shù)...
  • 限流的維度:時間、IP、用戶
  • 限流的實現(xiàn)層面:前端頁面、WEB代理、服務(wù)接口...

應(yīng)用場景

  1. 防止服務(wù)接口短時間涌入大量請求導(dǎo)致服務(wù)器資源快速耗盡最終服務(wù)無法訪問
  2. 突發(fā)流量時通過排隊策略實現(xiàn)流量削峰,杜絕對服務(wù)器的沖擊
  3. 針對ip、或用戶控制對某個資源的訪問次數(shù)
  4. 針對高頻接口,控制單位時間內(nèi)允許的請求次數(shù)
  5. 結(jié)合ip或其他因子防爬蟲

限流方法

這里我們主要討論后端基于請求量的限流,限流是一種非常廣泛的應(yīng)用技術(shù),就比如你在登錄系統(tǒng)時,經(jīng)常會需要你輸入手機驗證、動態(tài)碼或一些奇奇怪怪的驗證方式, 來降低登錄請求的頻次。

  • 計數(shù)限流

按數(shù)量進行控制,達到設(shè)置的閾值則進行限流,其中固定窗口,滑動窗口則是通過該方法實現(xiàn)。

  • 固定窗口

通過控制時間單元內(nèi)允許的請求數(shù)量,一旦達到閾值,則不會處理該請求后續(xù)相關(guān)的業(yè)務(wù)或者直接讓請求快速失敗并給予提示。

圖片

比如我們配置10s內(nèi)允許請求的流量為1000,在第1~9s內(nèi)請求為0,在第9~10秒內(nèi)的請求數(shù)為1000,這樣一秒內(nèi)的請求就達到了1000。當然我們可以時間單元劃分成更小粒度, 但是應(yīng)該多小才合適呢?

問題:只能對時間單元內(nèi)的總請求數(shù)進行控制,當請求集中在較小時間范圍內(nèi)時,無法達到流量限制的效果,因此這是一種粗粒度的流量限制手段

  • 滑動窗口

為了解決固定窗口算法中存在的問題,通過滑動窗口的方法,將上述時間單元劃分成多個細粒度的時間窗口,每個窗口都有自己獨立的請求計數(shù)器,這樣就可以讓時間單元內(nèi)的流量控制均勻地 落在各個時間窗口上,同時滑動的時間窗口可以形成連續(xù)時間區(qū)間控制,并不像固定窗口那樣只在兩個時間刻度間。

圖片

比如時間單元為1s,每個時間窗口為100ms,在1秒內(nèi)的10個時間窗口可以為09:01:01.000~09:01:02.000、09:01:01.200~09:01:02.800...

問題:滑動窗口的區(qū)間劃分的越多,則滑動窗口的滾動就越平滑,限流的統(tǒng)計就會越精確,但也需要更多的資源為窗口時間片段保存計數(shù)器,從而耗費系統(tǒng)資源

  • 漏桶算法

如果將請求看成水滴,限流器看成一個下面開口的桶(漏桶)。漏桶算法其實就是當水滴(請求)先進入到漏桶里,漏桶以一定的速度出水,當水流入速度過大時則會超過桶的可接納容量, 這時水將直接溢出,漏桶算法能強行限制數(shù)據(jù)的傳輸速率。使用漏桶算法,可以保證接口會以一個常速速率來處理請求,所以漏桶算法必定不會出現(xiàn)臨界問題。

圖片

問題:當短時間內(nèi)如果有大量的突發(fā)請求時,即使服務(wù)器負載不高,每個請求也需要等待一段時間(水滴間隔)才能被響應(yīng)

  • 令牌桶算法

令牌桶算法會以一個恒定的速度往桶里放入令牌,而如果請求需要被處理,則需要先從桶里獲取一個令牌,當桶里沒有令牌可取時,則拒絕服務(wù)。相比“漏桶算法”,“令牌桶算法”能夠在限制數(shù)據(jù)的平均傳輸速率的同時,還允許能應(yīng)對流量突增的情況(允許突發(fā)請求,只要有足夠的令牌,支持一次拿多個令牌)。

圖片

實現(xiàn)示例

固定窗口

public class FixedWindowLimiter {
/**
* 時間單元 ms
*/
private long timeUnit;

/**
* 時間單元內(nèi)的閾值
*/
private long limit;

/**
* 開始時間
*/
private long startTime;

/**
* 計數(shù)器
*/
private long count;

public FixedWindowLimiter(long timeUnit, long limit) {
this.timeUnit = timeUnit;
this.limit = limit;
}

/**
*
* @return
*/
public synchronized boolean acquire(){
long now = System.currentTimeMillis();
// 開始
if( startTime == 0 ){
startTime = now;
count ++;
return true;
}
// 在一個時間單元內(nèi)
if(now - startTime <= timeUnit){
count ++;
return count <= limit;
}else{// 超過時間單元、
startTime = now;
count = 0;
return true;
}
}

Guava RateLimiter

  • 令牌桶算法實現(xiàn)
  • 支持預(yù)熱
  • 支持突發(fā)流量

配置

說明

permitsPerSecond

單位時間內(nèi)產(chǎn)生令牌數(shù)量

warmupPeriod

預(yù)熱期

unit

預(yù)熱期時間單位

創(chuàng)建RateLimiter,每秒發(fā)放6個令牌,平均間隔167ms一個,其中有3秒的預(yù)熱期

    RateLimiter rateLimiter = RateLimiter.create(
6, // 每秒發(fā)放令牌數(shù)量
3, // 預(yù)熱期,在預(yù)熱期后逐步達到配置的令牌發(fā)放數(shù)量
TimeUnit.SECONDS // 時間單位
);

使用RateLimiter

    @Test
public void limit() throws InterruptedException {
Stopwatch stopwatch = Stopwatch.createStarted();
long last;
for (int i=0; i < 100; i++){
last = stopwatch.elapsed(TimeUnit.MILLISECONDS);
rateLimiter.acquire();
long duration = stopwatch.elapsed(TimeUnit.MILLISECONDS);
System.out.println( String.format("第%s次,距離開始的時間:%sms,間隔時間:%sms", i, duration, duration-last));

if( i == 20 ){
// 中間暫停5秒,看看申請令牌的時間間隔變化
TimeUnit.SECONDS.sleep(5);
System.out.println("暫停5秒后...");
long last2 = stopwatch.elapsed(TimeUnit.MILLISECONDS);
rateLimiter.acquire(10);
long duration2 = stopwatch.elapsed(TimeUnit.MILLISECONDS);
System.out.println( String.format("第%s次,距離開始的時間:%sms,間隔時間:%sms", i, duration2, duration2-last2));
}
}
}

結(jié)果:大約3秒后進入平穩(wěn)期

第0次,距離開始的時間:0ms,間隔時間:0ms
第1次,距離開始的時間:483ms,間隔時間:483ms
第2次,距離開始的時間:926ms,間隔時間:443ms
第3次,距離開始的時間:1334ms,間隔時間:408ms
第4次,距離開始的時間:1703ms,間隔時間:369ms
第5次,距離開始的時間:2036ms,間隔時間:333ms
第6次,距離開始的時間:2333ms,間隔時間:297ms
第7次,距離開始的時間:2592ms,間隔時間:259ms
第8次,距離開始的時間:2815ms,間隔時間:223ms
第9次,距離開始的時間:2999ms,間隔時間:184ms
第10次,距離開始的時間:3166ms,間隔時間:167ms
第11次,距離開始的時間:3333ms,間隔時間:167ms
第12次,距離開始的時間:3500ms,間隔時間:167ms
第13次,距離開始的時間:3666ms,間隔時間:166ms
...
暫停5秒后...
第20次,距離開始的時間:9842ms,間隔時間:0ms
第21次,距離開始的時間:13009ms,間隔時間:3166ms
第22次,距離開始的時間:13176ms,間隔時間:167ms
第23次,距離開始的時間:13342ms,間隔時間:166ms
第24次,距離開始的時間:13510ms,間隔時間:168ms
第25次,距離開始的時間:13676ms,間隔時間:166ms
第26次,距離開始的時間:13843ms,間隔時間:167ms
第27次,距離開始的時間:14009ms,間隔時間:166ms
  • 預(yù)熱期 系統(tǒng)剛啟動或者長時間沒有收到請求時,限流器處于冷卻狀態(tài),在預(yù)熱期間獲取令牌的時間會比平穩(wěn)期獲取令牌的時間要長,隨著令牌的減少,獲取單個令牌的時間會慢慢變短,最終到達一個穩(wěn)定值
  • acquire acquire是一個阻塞方法,通過RateLimiter會得到一個阻塞時間值
  • tryAcquire 非阻塞方法,快速返回令牌申請結(jié)果

結(jié)束語

作為微服務(wù)服務(wù)保證的三大利器,限流、熔斷、降級,了解其大概的大概的含義是非常有必要的,雖然現(xiàn)在有很多封裝好的限流框架,比如Sentinel、Resilience4j等,但技術(shù)是沒有止境的,當你往下探索 時,更多不可思議的知識,后面有機會我們從源碼,更底層來認識這些技術(shù)與設(shè)計思想。

責(zé)任編輯:武曉燕 來源: Java技術(shù)指北
相關(guān)推薦

2021-07-06 15:01:07

分布式架構(gòu)系統(tǒng)

2023-11-20 08:18:49

Netty服務(wù)器

2019-08-06 09:00:00

JavaScript函數(shù)式編程前端

2023-11-06 08:16:19

APM系統(tǒng)運維

2022-11-11 19:09:13

架構(gòu)

2016-10-25 14:35:05

分布式系統(tǒng) 存儲

2020-10-28 11:15:24

EPaxos分布式性算法

2022-02-24 07:34:10

SSL協(xié)議加密

2023-11-08 08:15:48

服務(wù)監(jiān)控Zipkin

2023-10-27 08:15:45

2020-02-02 15:14:24

HTTP黑科技前端

2020-10-08 14:32:57

大數(shù)據(jù)工具技術(shù)

2025-01-15 09:06:57

servlet服務(wù)器Java

2022-09-29 13:09:38

DataClassPython代碼

2022-04-28 09:22:46

Vue灰度發(fā)布代碼

2021-07-07 07:14:48

分布式ID分布式系統(tǒng)

2023-03-31 08:16:53

Flutter優(yōu)化內(nèi)存管理

2023-12-06 16:28:56

2019-07-04 15:16:52

數(shù)據(jù)挖掘大數(shù)據(jù)算法

2022-09-06 11:21:49

光網(wǎng)絡(luò)光纖
點贊
收藏

51CTO技術(shù)棧公眾號