[微服務感悟] 服務雪崩與熔斷器

  • 2020 年 2 月 13 日
  • 筆記

文章目錄

  • 什麼是服務雪崩
  • 解決方式
  • 熔斷器
  • 艙壁模式(服務隔離)

什麼是服務雪崩

之前工作中出現了這樣的一個問題,有一個業務服務,它的功能是政府某部門的文件流轉櫃。那個業務中原本每個外部請求都有一個獨立的線程池去處理任務,後來聽說spring支持全局的線程池。我們為了便於管理所有的線程,於是用spring建立一個全局現場池,讓所有異步請求都從spring提供的全局線程池拿線程執行。當時的異步調用有發送短訊,同步政府某部門業務數據等功能。有一天,我們的客戶反饋投件之後沒有發送短訊,我們查看日誌發現是線程池中堆積了很多同步政府業務數據的任務,日誌顯示所有的同步數據的請求都超時了。考慮這個外部請求只會在一些極少數的校驗業務中出現,不是主要業務,於是我們緊急的停掉了這個政府接口調用,重新上線,用戶又可以收到短訊了

這就是一個因為下游系統不可用導致服務資源池被耗盡問題。如果這個問題擴散一下,又有上游系統採用全局資源池調用這個業務系統的某些接口,這些接口又恰好同步的使用了線程池導致請求操時,這個上游系統就也會出現請求任務堆積資源池的情況,假設這個上游系統還有其他系統調用。。。,最會迅速導致這個微服務集群中,所有系統都像多米諾骨牌一樣,一個一個的資源耗盡返回操時,整個服務群都不可用了。

實際上導致一個服務節點不可用的原因有很多,網絡原因,bug,運維事務,數據庫/redis資源耗盡等,且隨着服務節點越多,其中一個節點出現不可用的概率就越大,直到無限等於1。

服務雪崩效應是一種因「服務提供者的不可用」(原因)導致「服務調用者不可用」(結果),並將不可用逐漸放大的現象

解決方式
熔斷器

熔斷器是對於一段時間內超時請求數超過設定值的服務器,之後對它的請求不訪問,直接返回失敗信息,以防止大量操時請求任務堆積。一般熔斷器還要設定一個過期時間,過期之後的的請求正常去請求。

if (outCount() < FuseThreshold) {    callRemote(url, params, headers);  } else {    throw new CallRemoteFailedException();  }

對於上個案例,我們後來使用redis的定時key特性實現了一個熔斷器。

大部分微服務架構都自帶熔斷器功能,只用配置一下就可以使用,如springCloud的Hystrix,建議先看看架構中是否存在熔斷器功能,不要自建輪子。

艙壁模式(服務隔離)

艙壁模式是服務的公用資源隔離開,一旦一個資源池耗盡,不會影響其他資源池的任務。比如案例的中最初的做法,一個外部調用一個線程池,一個外部調用不可用不會影響其他外部調用都不可用。

大部分微服務架構也自帶該功能,比如springCloud的Hystrix。