介面限流
介面限流
簡述
有時候,介面對外提供服務的時候,需要保護我們的介面,避免併發過大導致系統癱瘓。
限流演算法
常用的限流演算法存在兩種:漏桶演算法和令牌桶演算法。
漏桶演算法:故名思意,就是桶下面有個洞,以恆定的速率處理請求,請求過來放入桶中,請求量大於桶的容量益處,則拒絕服務。
令牌桶演算法:令牌桶演算法是一個存放固定容量令牌的桶,按照固定速率往桶裡新增令牌。令牌桶演算法的描述如下: 假設限制2r/s,則按照500毫秒的固定速率往桶中新增令牌; 桶中最多存放b個令牌,當桶滿時,新新增的令牌被丟棄或拒絕; 當一個n個位元組大小的資料包到達,將從桶中刪除n個令牌,接著資料包被髮送到網路上; 如果桶中的令牌不足n個,則不會刪除令牌,且該資料包將被限流(要麼丟棄,要麼緩衝區等待)
限流工具類RateLimiter
Google開源工具包Guava提供了限流工具類RateLimiter,該類基於令牌桶演算法來完成限流,非常易於使用。
方法摘要
修飾符和型別 | 方法和描述 |
---|---|
double | acquire()從RateLimiter獲取一個許可,該方法會被阻塞直到獲取到請求 |
double | acquire(int permits)從RateLimiter獲取指定許可數,該方法會被阻塞直到獲取到請求 |
static RateLimiter | create(double permitsPerSecond)根據指定的穩定吞吐率建立RateLimiter,這裡的吞吐率是指每秒多少許可數(通常是指QPS,每秒多少查詢) |
static RateLimiter | create(double permitsPerSecond, long warmupPeriod, TimeUnit unit)根據指定的穩定吞吐率和預熱期來建立RateLimiter,這裡的吞吐率是指每秒多少許可數(通常是指QPS,每秒多少個請求量),在這段預熱時間內RateLimiter每秒分配的許可數會平穩地增長直到預熱期結束時達到其最大速率。(只要存在足夠請求數來使其飽和) |
double | getRate()返回RateLimiter 配置中的穩定速率,該速率單位是每秒多少許可數 |
void | setRate(double permitsPerSecond)更新RateLimite的穩定速率,引數permitsPerSecond 由構造RateLimiter的工廠方法提供。 |
String | toString()返回物件的字元表現形式 |
boolean | tryAcquire()從RateLimiter 獲取許可,如果該許可可以在無延遲下的情況下立即獲取得到的話 |
boolean | tryAcquire(int permits)從RateLimiter 獲取許可數,如果該許可數可以在無延遲下的情況下立即獲取得到的話 |
boolean | tryAcquire(int permits, long timeout, TimeUnit unit)從RateLimiter 獲取指定許可數如果該許可數可以在不超過timeout的時間內獲取得到的話,或者如果無法在timeout 過期之前獲取得到許可數的話,那麼立即返回false (無需等待) |
boolean | tryAcquire(long timeout, TimeUnit unit)從RateLimiter 獲取許可如果該許可可以在不超過timeout的時間內獲取得到的話,或者如果無法在timeout 過期之前獲取得到許可的話,那麼立即返回false(無需等待) |
舉例
一個秒殺活動限流例子。每秒限流10個請求
import com.google.common.base.Stopwatch;
import com.google.common.util.concurrent.RateLimiter;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author td
* @date 2017/09/13
*/
public class TokenBucket {
private AtomicInteger phoneNumbers = new AtomicInteger(0);
private final static int LIMIT = 100;
private RateLimiter rateLimiter = RateLimiter.create(10);
private final int saleLimit;
public TokenBucket() {
this(LIMIT);
}
public TokenBucket(int saleLimit) {
this.saleLimit = saleLimit;
}
public int buy() {
Stopwatch stopwatch = Stopwatch.createStarted();
boolean success = rateLimiter.tryAcquire(10, TimeUnit.MILLISECONDS);
if (success) {
int phoneNum = phoneNumbers.getAndIncrement();
if (phoneNum>=saleLimit) {
throw new IllegalStateException("not any phone can be sale,please wait to next time.");
}
handleOrder();
System.out.println(Thread.currentThread()+"user get the phone "+phoneNum+",ELT:"+stopwatch.stop());
return phoneNum;
}else {
stopwatch.stop();
throw new RuntimeException("Sorry,occur excepiton when buy phone");
}
}
private void handleOrder() {
try {
TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* @author td
* @date 2017/09/13
*/
public class TokenBucketExample {
public static void main(String[] args) {
final TokenBucket tokenBucket = new TokenBucket();
for (int i=0;i< 200;i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(tokenBucket::buy).start();
}
}
}
相關文章
- 介面限流實踐
- ASP.NET Core Web API 介面限流ASP.NETWebAPI
- redis+lua指令碼實現介面限流Redis指令碼
- 介面限流演算法:漏桶演算法&令牌桶演算法&redis限流演算法Redis
- php令牌桶演算法實現介面限流PHP演算法
- Spring Cloud Gateway 原生支援介面限流該怎麼玩SpringCloudGateway
- Spring Cloud Alibaba基礎教程:使用Sentinel實現介面限流SpringCloud
- Asp-Net-Core開發筆記:使用原生的介面限流功能筆記
- Nginx限流Nginx
- 介面限流演算法:漏桶演算法&令牌桶演算法演算法
- 單機限流和分散式應用限流分散式
- 限流場景&限流方案的一些思考
- Guava RateLimiter限流GuavaMIT
- Nginx限流特技Nginx
- Nginx分片限流Nginx
- 分散式限流分散式
- 【高併發】億級流量場景下如何為HTTP介面限流?看完我懂了!!HTTP
- Asp-Net-Core開發筆記:使用RateLimit中介軟體實現介面限流筆記MIT
- 高可用之限流-03-Semaphore 訊號量做限流
- nginx 限流配置Nginx
- Redis 應用-限流Redis
- 淺談Api限流API
- Java Redis多限流JavaRedis
- nginx做限流設定Nginx
- sbc(四)應用限流
- Sentinel 實戰-限流篇
- 使用Redis進行限流Redis
- 常用限流演算法演算法
- 5種限流演算法,7種限流方式,擋住突發流量?演算法
- Guava RateLimiter限流器使用示例GuavaMIT
- go-kit微服務:限流Go微服務
- 簡析限流演算法演算法
- nginx之 nginx限流配置Nginx
- 限流演算法介紹演算法
- redis實際應用-限流Redis
- AspNetCore新增API限流NetCoreAPI
- Spring Cloud Gateway 限流操作SpringCloudGateway
- 專案如何實現限流?