限流的解決方式
1、計數器算法:在一段時間間隔內(時間窗/時間區間),處理請求的最大數量固定,超過部分不做處理。
bug:
假設有一個惡意用戶,他在0:59時,瞬間發送了100個請求,並且1:00又瞬間發送了100個請求,那么其實這個用戶在 1秒里面,瞬間發送了200個請求。
我們剛才規定的是1分鍾最多100個請求(規划的吞吐量),也就是每秒鍾最多1.7個請求,用戶通過在時間窗口的重置節點處突發請求, 可以瞬間超過我們的速率限制。
用戶有可能通過算法的這個漏洞,瞬間壓垮我們的應用。
2、漏桶算法
水(請求)進入到漏桶里,按照一定速率流出,當水流入過大超過桶得容量時會自動溢出。
做到了:
削峰:有大量請求到來時,會拒絕(自動溢出),不會使服務器突然壓力劇增,從而限流保護服務可用。
緩沖:不至於直接請求到服務器,緩沖壓力。
bug:
出水速度固定即請求放行速度固定。無法應對特殊緊急情況。比如,通過動態擴容,后端流量從1000QPS提升到1WQPS,漏桶沒有辦法。
3、令牌桶
以一個設定的速率產生令牌並放入令牌桶,每次用戶請求都得申請令牌,如果令牌不足,則拒絕請求。
令牌桶限流大致的規則如下:
(1)進水口按照某個速度,向桶中放入令牌。
(2)令牌的容量是固定的,但是放行的速度不是固定的,只要桶中還有剩余令牌,一旦請求過來就能申請成功,然后放行。
(3)如果令牌的發放速度,慢於請求到來速度,桶內就無牌可領,請求就會被拒絕。
總之,令牌的發送速率可以設置,從而可以對突發的出口流量進行有效的應對。
令牌桶的好處之一就是可以方便地應對 突發出口流量(后端能力的提升)。
比如,可以改變令牌的發放速度,算法能按照新的發送速率調大令牌的發放數量,使得出口突發流量能被處理。
《小日常》
小F:
高並發的場景應該怎么考慮呀?
大M:
高並發一般解決辦法就是,代碼調優,加redis來減少數據庫壓力,加mq來緩解服務器壓力,增加熔斷和限流,防止服務雪崩導致業務阻斷;最后就是提高硬件配置,加服務器的節點,提高數據庫服務器cpu內存等。
大M:
可以通過mq來緩解服務的壓力,把訂單請求放到mq里,然后后台服務來消費mq。相當於mq起一個緩沖的作用
小F:
增加熔斷和限流?
大M:
熔斷:熔斷就是,如果A服務請求B1服務,B1服務由於並發太高了,然后宕機了,這時候A服務沒收到B1的返回結果,之后就不會去請求B1服務了,只會去請求B2,B3
小F:
噢噢噢,springCloud框架中hystrix組件就可以實現熔斷。
大M:
對,限流:限流是通過令牌桶來實現的,就比如一分鍾生成1000個令牌,每個請求過來都會從令牌桶里刪除一個令牌,這樣的話,當一分鍾請求超過1000個的時候,就拿不到令牌了,就請求失敗了;springcloud有專門的依賴來做這個的,用redis來放令牌的