雷の群れ問題

解決API的雷鳴群問題:如何應對突然的流量激增

在2018年4月,我在一家初創公司工作,該公司即將推出一個廣受期待的新功能。我們通過建立等候名單來引起對該功能的興趣,但我們對上線日期保持了相當的保密(主要是因為我們不知道開發何時會完成)。

在完成最後的功能以實現MVP的完整性後,我們進行了一些輕量級的測試,以確保所有用戶的操作都按照我們的預期進行。情況看起來不錯,經過與產品經理的討論,我們決定將其對所有客戶開放。然而,由於整個公司都因為上線了一個大功能而興奮不已,不知不覺中,推送通知已經發送給所有客戶,並且整個等候名單已經啟用。

我們沒有預料到開始收到的流量激增,很快就收到了服務崩潰的警報,原因是我們未能處理的未知崩潰。修復後,我們重新部署了它,短暫的時間內,所有的警報都解決了,我們可以放鬆一下。然而,這種放鬆並沒有持續多久,5分鐘後,又出現了一系列不同的警報(高延遲,高CPU使用率)。我們又進入了事故模式。

不幸的是,我們第一次親身經歷了雷鳴群問題。

對於API而言,雷鳴群問題通常發生在大量客戶或服務在一段時間的不可用或延遲後同時發送請求到API。這可能是由您擁有的服務或第三方服務在一段停機或不穩定期後重試請求引起的。

這些請求通常不是惡意的,而是由工程師試圖做正確的事情引起的;當我們在分布式系統上工作時,我們首先得到的教訓之一就是網絡是不可靠的,我們應該假設它們會失敗。這是一個很好的建議,但我們如何處理這種故障很重要。

為了解決即時的問題,我們需要減少請求的數量,或者擴展我們的API可以處理的請求量(最好兩者兼顧)。您可以進行以下操作:

水平擴展您的API:如果選擇此選項,請確保密切關注您的數據庫健康狀況,特別是如果您過去沒有將API進行水平擴展。如果您沒有拆分讀寫請求或連接池,您可能會發現自己遇到數據庫問題!

垂直擴展您的API:這可能不總是有效,但通常CPU、內存和應用程序處理的請求量之間存在某種關係。

降低一些不太重要的工作負載:也許在短期內,有一些客戶操作我們可以有意識地影響,同時使自己回到一個更穩定的狀態。例如,您可能會決定在這段時間內不允許新客戶註冊。對於其他公司來說,這可能是最糟糕的事情,註冊是我們必須確保繼續進行的關鍵操作。如果您尚未進行這些討論,請確保在公司內進行這些討論。

我們擴展了我們的API,降低了其他服務的工作負載,現在我們又回到了正常運作的狀態。但壓力並沒有完全消失,因為我們知道這種情況隨時可能再次發生。我們該怎麼做才能防止這種情況發生?我們需要從幾個角度來解決它。讓我們一步一步地進行,首先從API所需的更改開始。

首先,我們應該考慮添加每個客戶的請求速率限制。您可以在基礎設施層(許多負載均衡器或反向代理支持此功能)或應用程序中進行此操作。無論哪種方式,給客戶一個每分鐘可以發出多少請求的限制是保護您的API的有用方式。決定每個應用程序的速率限制是一門不完美的科學,需要一些實驗。我建議您的API返回Retry-After標頭,客戶可以使用它來確定“後退”多長時間。這種方法的好處是,您可以鼓勵客戶使用指數後退行為。

您可以考慮在API中實施緩存,以避免進行昂貴的數據庫查找或計算。這對於所有API都不適用,有一句話說“如果您使用緩存解決了一個問題,您現在有了一個問題”,這是值得記住的,每當您尋求它作為解決方案時。AWS有一篇名為“緩存的歡愉與痛苦”的優秀文章,我強烈推薦閱讀。

您可以考慮在API中添加斷路器,以便一旦開始看到請求激增,您可以打開斷路器,防止處理更多請求。對於Go,這裡有一些開源庫可以使用,例如sony/gobreaker或go-kit提供的庫。

在上面描述的情況中,我們實際上設置了警報,這使我們能夠捕捉到問題,但損害已經造成。如果我們可以在問題發生之前提前看到問題的跡象,我們就可以採取行動,進行垂直或水平擴展,以防止它成為問題。如果我們可以在問題發生之前使用這些早期警告信號來開始擴展並自動解決問題,那就更好了!

對於調用您的API的客戶端,您需要與他們合作,確保他們能夠成功地回應您的速率限制。此外,如果他們收到故障響應(5xx範圍內的響應),您可能需要要求他們實施指數後退和一點點抖動,以確保重試的請求在停機期間“分散”處理。Sam Rose制作了一個優秀的重試模式可視化,這應該有助於您看到不同策略對API的影響。

與API一樣,緩存也是值得考慮的。客戶端是否需要最新的信息?在本地存儲一些API響應是否可以減輕API的負載並改

注意

  • この記事はAI(gpt-3.5-turbo)によって自動生成されたものです。
  • この記事はHackerNewsに掲載された下記の記事を元に作成されています。
    The Thundering Herd Problem
  • 自動生成された記事の内容に問題があると思われる場合にはコメント欄にてご連絡ください。

コメントする