您好,登錄后才能下訂單哦!
雙11的高并發(fā)流量是如何抗住,很多新手對此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。
服務(wù)等級協(xié)議
我們常說的 N 個(gè) 9,就是對 SLA 的一個(gè)描述。SLA 全稱是 Service Level Agreement,翻譯為服務(wù)水平協(xié)議,也稱服務(wù)等級協(xié)議,它表明了公有云提供服務(wù)的等級以及質(zhì)量。
例如阿里云對外承諾的就是一個(gè)服務(wù)周期內(nèi)集群服務(wù)可用性不低于 99.99%,如果低于這個(gè)標(biāo)準(zhǔn),云服務(wù)公司就需要賠償客戶的損失。
做到 4 個(gè) 9 夠好了嗎
對互聯(lián)網(wǎng)公司來說,SLA 就是網(wǎng)站或者 API 服務(wù)可用性的一個(gè)保證。
9 越多代表全年服務(wù)可用時(shí)間越長服務(wù)更可靠,4 個(gè) 9 的服務(wù)可用性,聽起來已經(jīng)很高了,但對于實(shí)際的業(yè)務(wù)場景,這個(gè)值可能并不夠。
我們來做一個(gè)簡單的計(jì)算,假設(shè)一個(gè)核心鏈路依賴 20 個(gè)服務(wù),強(qiáng)依賴同時(shí)沒有配置任何降級,并且這 20 個(gè)服務(wù)的可用性達(dá)到 4 個(gè) 9,也就是 99.99%。
微服務(wù)的雪崩效應(yīng)
限流降級怎么做
緩存以及隊(duì)列等手段,增加系統(tǒng)的容量。限流和降級則是關(guān)心在到達(dá)系統(tǒng)瓶頸時(shí)系統(tǒng)的響應(yīng),更看重穩(wěn)定性。
限流和降級
超時(shí)降級
失敗次數(shù)降級
故障降級
熔斷隔離
如果不對服務(wù)資源做隔離,一旦一個(gè)服務(wù)出現(xiàn)了問題,整個(gè)系統(tǒng)的穩(wěn)定性都會(huì)受到影響!服務(wù)隔離的目的就是避免服務(wù)之間相互影響。
何處隔離:一次服務(wù)調(diào)用,涉及到的是服務(wù)提供方和調(diào)用方,我們所指的資源,也是兩方的服務(wù)器等資源,服務(wù)隔離通常可以從提供方和調(diào)用方兩個(gè)方面入手。
隔離什么:廣義的服務(wù)隔離,不僅包括服務(wù)器資源,還包括數(shù)據(jù)庫分庫,緩存,索引等,這里我們只關(guān)注服務(wù)層面的隔離。
降級和熔斷的區(qū)別
熔斷,一般是停止服務(wù):典型的就是股市的熔斷,如果大盤不受控制,直接休市,不提供服務(wù),是保護(hù)大盤的一種方式。
降級,通常是有備用方案:從北京到濟(jì)南,下雨導(dǎo)致航班延誤,我可以乘坐高鐵,如果高鐵票買不到,也可以乘坐汽車或者開車過去。
兩者的區(qū)別:降級一般是主動(dòng)的,有預(yù)見性的,熔斷通常是被動(dòng)的,服務(wù) A 降級以后,一般會(huì)有服務(wù) B 來代替,而熔斷通常是針對核心鏈路的處理。
常用限流算法設(shè)計(jì)
計(jì)數(shù)器法
這時(shí)候判斷,如果計(jì)數(shù)器的值小于限流值,并且與上一次請求的時(shí)間間隔還在一分鐘內(nèi),允許請求通過,否則拒絕請求,如果超出了時(shí)間間隔,要將計(jì)數(shù)器清零。
public class CounterLimiter {
//初始時(shí)間
private static long startTime = System.currentTimeMillis();
//初始計(jì)數(shù)值
private static final AtomicInteger ZERO = new AtomicInteger(0);
//時(shí)間窗口限制
private static final long interval = 10000;
//限制通過請求
private static int limit = 100;
//請求計(jì)數(shù)
private AtomicInteger requestCount = ZERO;
//獲取限流
public boolean tryAcquire() {
long now = System.currentTimeMillis();
//在時(shí)間窗口內(nèi)
if (now < startTime + interval) {
//判斷是否超過最大請求
if (requestCount.get() < limit) {
requestCount.incrementAndGet();
return true;
}
return false;
} else {
//超時(shí)重置
startTime = now;
requestCount = ZERO;
return true;
}
}
}
漏桶算法
漏桶算法的示意圖如下:
這里簡單實(shí)現(xiàn)一下,也可以使用 Guava 的 SmoothWarmingUp 類,可以更好的控制漏桶算法:
public class LeakyLimiter {
//桶的容量
private int capacity;
//漏水速度
private int ratePerMillSecond;
//水量
private double water;
//上次漏水時(shí)間
private long lastLeakTime;
public LeakyLimiter(int capacity, int ratePerMillSecond) {
this.capacity = capacity;
this.ratePerMillSecond = ratePerMillSecond;
this.water = 0;
}
//獲取限流
public boolean tryAcquire() {
//執(zhí)行漏水,更新剩余水量
refresh();
//嘗試加水,水滿則拒絕
if (water + 1 > capacity) {
return false;
}
water = water + 1;
return true;
}
private void refresh() {
//當(dāng)前時(shí)間
long currentTime = System.currentTimeMillis();
if (currentTime > lastLeakTime) {
//距上次漏水的時(shí)間間隔
long millisSinceLastLeak = currentTime - lastLeakTime;
long leaks = millisSinceLastLeak * ratePerMillSecond;
//允許漏水
if (leaks > 0) {
//已經(jīng)漏光
if (water <= leaks) {
water = 0;
} else {
water = water - leaks;
}
this.lastLeakTime = currentTime;
}
}
}
}
令牌桶算法
如果令牌不被消耗,或者被消耗的速度小于產(chǎn)生的速度,令牌就會(huì)不斷地增多,直到把桶填滿。后面再產(chǎn)生的令牌就會(huì)從桶中溢出。
最后桶中可以保存的最大令牌數(shù)永遠(yuǎn)不會(huì)超過桶的大小,每當(dāng)一個(gè)請求過來時(shí),就會(huì)嘗試從桶里移除一個(gè)令牌,如果沒有令牌的話,請求無法通過。
public class TokenBucketLimiter {
private long capacity;
private long windowTimeInSeconds;
long lastRefillTimeStamp;
long refillCountPerSecond;
long availableTokens;
public TokenBucketLimiter(long capacity, long windowTimeInSeconds) {
this.capacity = capacity;
this.windowTimeInSeconds = windowTimeInSeconds;
lastRefillTimeStamp = System.currentTimeMillis();
refillCountPerSecond = capacity / windowTimeInSeconds;
availableTokens = 0;
}
public long getAvailableTokens() {
return this.availableTokens;
}
public boolean tryAcquire() {
//更新令牌桶
refill();
if (availableTokens > 0) {
--availableTokens;
return true;
} else {
return false;
}
}
private void refill() {
long now = System.currentTimeMillis();
if (now > lastRefillTimeStamp) {
long elapsedTime = now - lastRefillTimeStamp;
int tokensToBeAdded = (int) ((elapsedTime / 1000) * refillCountPerSecond);
if (tokensToBeAdded > 0) {
availableTokens = Math.min(capacity, availableTokens + tokensToBeAdded);
lastRefillTimeStamp = now;
}
}
}
}
漏桶和令牌桶的比較
使用 RateLimiter 實(shí)現(xiàn)限流
RateLimter 提供的 API 可以直接應(yīng)用,其中 acquire 會(huì)阻塞,類似 JUC 的信號(hào)量 Semphore,tryAcquire 方法則是非阻塞的:
public class RateLimiterTest {
public static void main(String[] args) throws InterruptedException {
//允許10個(gè),permitsPerSecond
RateLimiter limiter = RateLimiter.create(10);
for(int i=1;i<20;i++){
if (limiter.tryAcquire(1)){
System.out.println("第"+i+"次請求成功");
}else{
System.out.println("第"+i+"次請求拒絕");
}
}
}
}
總結(jié)
看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請關(guān)注億速云行業(yè)資訊頻道,感謝您對億速云的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。