應對介面級的故障

_sanjun發表於2019-04-17
  • 注:文章來源:極客時間的專欄《從0開始學架構》

導致介面級故障的原因

內部原因
  • 程式bug導致死迴圈
  • 某個介面導致資料庫慢查詢
  • 程式邏輯不完善導致耗盡記憶體等
外部原因
  • 黑客攻擊、促銷或者搶購引入了超出平時幾倍甚至幾十倍的使用者
  • 第三方系統大量請求
  • 第三方系統響應緩慢等

解決介面故障的核心思想

  • 優先保證核心業務和優先保證絕大部分使用者
  • 丟車保帥,優先保證核心業務

降級

  • 降級指系統將某些業務或者介面的功能降低,可以是隻提供部分功能,也可以是完全停掉所有功能
案例
  • 雙11,訂單暫時不允許修改收貨地址
  • 論壇,降級為只能看帖子,不能發帖子
  • App的日誌上傳介面,可以完全停掉一段時間,這段時間內APP都不能上傳日誌
常見的實現降級的方式有:
  • 系統後門降級

  例如,系統提供一個降級URL,當訪問這個URL時,就相當於執行降級指令,具體的降級指令通過URL的引數傳入即可

缺點:安全隱患,伺服器數量多,需要一臺一臺去操作

  • 獨立降級系統

  將降級操作獨立到一個單獨的系統中,可以實現複雜的許可權管理、批量操作等功能。其基本架構如下:

應對介面級的故障

熔斷

  • 降級的目的是應對系統自身的故障,而熔斷的目的是應對依賴的外部系統故障的情況
案例
  • A服務的X功能依賴B服務的某個介面,當B服務的介面響應很慢的時候,A服務的X功能響應肯定被拖慢,進一步導致A服務的執行緒都被卡在X功能處理上,此時A服務的其他功能都會被卡住或者響應非常慢
  • 加入熔斷機制後,A服務不再請求B服務這個介面,A服務內部只要發現是請求B服務的這個介面就立即返回錯誤,從而避免A服務整個被拖慢甚至拖死
實現
  • 關鍵是需要有一個統一的API呼叫層,由API呼叫層來進行取樣或者統計,如果介面呼叫散落在程式碼各處就沒法進行統一處理了
  • 另一個關鍵是閾值的設計,例如1分鐘內30%的請求響應時間超過1秒就熔斷,這個策略的“1分鐘”“30%”“1秒”都對最終的熔斷效果有影響
  • 實踐中一般都是先根據分析再確定閾值,然後上線觀察效果,再進行調優

限流

  • 降級是從系統功能優先順序的角度考慮如何應對故障,而限流則是從使用者訪問壓力的角度來考慮如何應對故障
  • 限流指只允許系統能夠承受的流量進來,超出系統訪問能力的請求將被丟棄
常見的限流方式
  • 基於請求限流

  是指從外部訪問的請求角度考慮限流

  常見方式:限制總量、限制時間量

  限制總量:限制某個指標的累積上限

  例如,某個直播間限制總使用者數上限為100萬,超過後無法進入;搶購活動商品數量100個,限制參與使用者1萬個,超過1萬個後直接拒絕

  限制時間量:限制一段時間內某個指標的上限

  例如,1分鐘內只允許10000個使用者訪問,每秒請求峰值最高為10萬

  缺點:閾值難於確定
  • 基於資源限流

  是指從系統內部考慮的,找到系統內部影響效能的關鍵資源,對其使用上限進行限制

  常見的內部資源:連線數、檔案控制程式碼、執行緒數、請求佇列等

  例如,採用Netty來實現伺服器,每個進來的請求都先放入一個佇列,業務執行緒再從佇列讀取請求進行處理,佇列長度最大值為10000,佇列滿了就拒絕後面的請求;也可以根據CPU的負載或者佔用率進行限流,當CPU的佔用率超過80%的時候就開始拒絕新的請求

  缺點:難於確定關鍵資源及其閾值
  實現方案:逐步調優,開始時先根據推斷選擇某個關鍵資源和閾值,然後測試驗證,再上線觀察,不合理再優化。

排隊

  • 排隊是限流的一個變種,限流是直接拒絕使用者,排隊是讓使用者等待一段時間

  • 由於排隊需要臨時快取大量的業務請求,單個系統內部無法快取這麼多資料,一般情況下,排隊需要用獨立的系統去實現,例如使用Kafka這類訊息佇列來快取使用者請求

    應對介面級的故障

  • 排隊模組

  將請求以先入先出的方式儲存下來,每一個參加秒殺的商品儲存一個佇列

  • 排程模組

  負責排隊模組到服務模組的動態排程,不斷檢查服務模組,一旦處理能力有空閒,就從排隊佇列頭上把使用者訪問資源請求調入服務模組,並負責向服務模組分發請求

  • 服務模組

  負責呼叫真正業務來處理服務,並返回處理結果,呼叫排隊模組的介面回寫業務處理結果

注:有興趣瞭解極客時間專欄的同學,可以檢視極客時間專欄—可提供返現服務

相關文章