限流是指在一段時間內(nèi),定義某個客戶或應(yīng)用可以接收或處理多少個請求的技術(shù)。例如,通過限流,你可以過濾掉產(chǎn)生流量峰值的客戶和微服務(wù),或者可以確保你的應(yīng)用程序在自動擴展(Auto Scaling)失效前都不會出現(xiàn)過載的情況。
你還可以阻止較低優(yōu)先級的流量,以便為關(guān)鍵事務(wù)提供足夠的資源。
限流器可以阻止流量峰值
另外有一種限流器,稱為 “并發(fā)請求限流器(concurrent request limiter)”。當你有一些比較昂貴和重要的端點(endpoint),希望它不應(yīng)該被調(diào)用超過指定的次數(shù),但仍然想要提供流量服務(wù)時,這個限流器就十分有用了。
使用負載開關(guān)可以確保對于關(guān)鍵的事務(wù)總能提供足夠的資源保障。它為高優(yōu)先級的請求保留一些資源,并且不允許低優(yōu)先級的事務(wù)去占用這些資源。負載開關(guān)會根據(jù)系統(tǒng)的整體狀態(tài)做出決定,而不是基于單個用戶的請求桶(request bucket)大小。負載設(shè)備有助于你的系統(tǒng)恢復(fù),因為它們在持續(xù)發(fā)生故障事件時,依然能保持核心功能正常工作。
關(guān)于更多限流器和負載開關(guān)的知識,建議讀者參考Stripe的相關(guān)文章。
快速且單獨失效(Fail Fast and Independently)
在微服務(wù)體系架構(gòu)中,我們希望服務(wù)可以快速、單獨地失效。為了在服務(wù)層面隔離故障,我們可以使用隔板模式(bulkhead pattern)。可以在本文稍后看到相關(guān)介紹。
我們也希望我們的組件能夠快速失效(fail fast),因為我們不希望等到斷開的實例直到超時。沒有什么比掛起的請求和無響應(yīng)的界面更令人失望。這不僅浪費資源,而且還會讓用戶體驗變得更差。我們的服務(wù)是互相調(diào)用的,所以在這些延遲疊加前,應(yīng)該特別注意防止那些超時的操作。
你想到的第一個辦法,可能是對每個服務(wù)的調(diào)用都定義超時的級別。這種做法的問題是,你不能真正知道到底什么是恰當?shù)某瑫r值,因為當網(wǎng)絡(luò)故障和其他問題發(fā)生時,某些情況下只會影響一兩次操作。在這種情況下,如果只有其中一些發(fā)生超時,你可能不想拒絕所有這些請求。
我們可以說,通過使用超時(timeout)來實現(xiàn)微服務(wù)中的快速失敗是一種反模式,這是應(yīng)該避免的??梢允褂没诓僮鞯某晒?失敗統(tǒng)計次數(shù)的熔斷模式,而不是使用超時。
艙壁模式(Bulkheads)
在工業(yè)領(lǐng)域中,常使用艙壁將劃分為幾個部分,以便在有某部分船體發(fā)生破裂時,其他部分依然能密封安然無恙。
艙壁的概念也可以在軟件開發(fā)中用于隔離資源。
通過使用艙壁模式,我們可以保護有限的資源不被用盡。例如,如果我們有兩種類型的操作的話,它們都是和同一個數(shù)據(jù)庫實例進行通信,并且數(shù)據(jù)據(jù)庫限制連接數(shù),這時我們可以使用兩個連接池而不是使用一個共享的連接池。由于這種客戶端和資源分離,超時或過度使用池的操作不會令所有其他操作失效。
泰坦尼克號沉沒的主要原因之一是其艙壁設(shè)計失敗,水可以通過上面的甲板倒在艙壁的頂部,最后整個船淹沒。
泰坦尼克號故障的艙壁
斷路器(Circuit Breakers)
為了限制操作的持續(xù)時間,我們可以使用超時。超時可以防止掛起操作并保證系統(tǒng)可以響應(yīng)。然而,在微服務(wù)架構(gòu)通信中使用靜態(tài)、微調(diào)的超時是一種反模式,因為我們處于高度動態(tài)的環(huán)境中,幾乎不可能確定在每種情況下都能正常工作的準確的時間限制。
我們可以使用斷路器來處理錯誤,而不是使用小型和特定基于事務(wù)的靜態(tài)超時機制。斷路器以現(xiàn)實世界的電子元件命名,因為它們的行為是都是相同的。你可以保護資源,并通過使用斷路器協(xié)助它們進行恢。斷路器在分布式系統(tǒng)中非常有用,因為重復(fù)的故障可能會導(dǎo)致雪球效應(yīng),并使整個系統(tǒng)崩潰。