場景:例如A服務(wù)能夠處理每秒200個請求。如果B系統(tǒng)調(diào)用A系統(tǒng)的請求頻率超過這個頻率,A服務(wù)器就可能會掛掉。我們可以對A服務(wù)器做限流。
常見的限流技術(shù)主要分為:nginx限流,后端Tomcat服務(wù)器限流,后端服務(wù)器技術(shù)限流(漏桶算法,令牌桶)
tomcat限流
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
maxThreads="150"
redirectPort="8443" />
在tomcat的config文件夾下有maxThreads 就是 Tomcat 的最大線程數(shù),當(dāng)請求的并發(fā)大于此值(maxThreads)時,請求就會排隊執(zhí)行,這樣就完成了限流的目的。
nginx限流
Nginx 提供了兩種限流手段:一是控制速率,二是控制并發(fā)連接數(shù)。
控制速率
我們需要使用 limit_req_zone 用來限制單位時間內(nèi)的請求數(shù),即速率限制。
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s;
server {
location / {
limit_req zone=mylimit;
}
}
限制每個 IP 訪問的速度為 2r/s,因為 Nginx 的限流統(tǒng)計是基于毫秒的,我們設(shè)置的速度是 2r/s,轉(zhuǎn)換一下就是 500ms 內(nèi)單個 IP 只允許通過 1 個請求,從 501ms 開始才允許通過第 2 個請求。
控制并發(fā)數(shù)
利用 limit_conn_zone 和 limit_conn 兩個指令即可控制并發(fā)數(shù)

其中 limit_conn perip 10 表示限制單個 IP 同時最多能持有 10 個連接;limit_conn perserver 100 表示 server 同時能處理并發(fā)連接的總數(shù)為 100 個。
后臺服務(wù)器限流技術(shù)
漏桶算法
算法思路:水(請求)先進(jìn)入漏桶里,漏桶以恒定的速度流出,當(dāng)流出的速度大于進(jìn)入的速度,就會溢出,可以看出漏桶算法限制數(shù)據(jù)傳輸?shù)乃俣取?/p>

漏桶算法的實現(xiàn)步驟是,先聲明一個隊列用來保存請求,這個隊列相當(dāng)于漏斗,當(dāng)隊列容量滿了之后就放棄新來的請求,然后重新聲明一個線程定期從任務(wù)隊列中獲取一個或多個任務(wù)進(jìn)行執(zhí)行,這樣就實現(xiàn)了漏桶算法。
redis提供了 Redis-Cell 模塊。

15:是max_burst,就是初始時,最大的容量,就是令牌桶初始時的數(shù)量,但是初始化數(shù)量是該值加一。
30/60 ;漏斗滴水的速率。 在指定時間內(nèi)窗口內(nèi)允許訪問的次數(shù)
apply 1 token 獲取的令牌
令牌桶
令牌桶算法的原理是系統(tǒng)會以一個恒定的速度往桶里放入令牌,而如果請求需要被處理,則需要先從桶里獲取一個令牌,當(dāng)桶里沒有令牌可取時,則拒絕服務(wù)。

依賴
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.1-jre</version>
</dependency>
java代碼
RateLimiter limiter = RateLimiter.create(1000);
@RequestMapping("/hello")
public String hello(){
String result = "";
boolean tryAcquire = limiter.tryAcquire(1000, TimeUnit.MILLISECONDS);
if(!tryAcquire){
result = "被限流了服務(wù)降級";
return result;
}
result = sqlService.sayHello();
return result;
}