SpringCloud(三) 微服務架構-微服務穩定性


  采用微服務架構后,當分布式系統到達一定量級時,每個環境都可能出錯,因此在系統設計時應該考慮如何減輕故障的影響,如何從故障中快速恢復。一般從以下兩點來考察系統的穩定性:

  • 高可用:當前服務依賴的下游服務性能降低或者失敗時,該服務怎么相應,是快速失敗還是重試?大促時如何應對瞬間涌入的流量?
  • 高並發:底層服務如何保證服務的吞吐量?如何提高消費者的處理速度?

高可用

限流

   限流算法

  計數器法:該算法維護一個counter,規定在單位時間內counter的大小不能超過最大值,每隔固定時間就將counter的值置為零。

  漏桶算法:水(請求)先進入到漏桶里,漏桶以一定的速度出水,當水流入速度過大會直接溢出(拒絕服務),可以看出漏桶算法能強行限制數據的傳輸速率

   

  令牌桶算法:一個存放固定容量令牌的桶,按照固定速率(每秒/或者可以自定義時間)往桶里添加令牌,然后每次獲取一個令牌,當桶里沒有令牌可取時,則拒絕服務。令牌桶分為2個動作,動作1(固定速率往桶中存入令牌)、動作2(客戶端如果想訪問請求,先從桶中獲取token)

  

 

 

   限流實踐

   Google開源工具包Guava提供了限流工具類RateLimiter,該類基於令牌桶算法(Token Bucket)來完成限流,非常易於使用.RateLimiter經常用於限制對一些物理資源或者邏輯資源的訪問速率.它支持兩種獲取permits接口,一種是如果拿不到立刻返回false,一種會阻塞等待一段時間看能不能拿到.

  RateLimiter設計思路:RateLimiter的主要功能就是通過限制請求流入的速度來提高穩定的服務速度。實現QPS速率的最簡單的方式就是記住上一次請求的最后授權時間,然后保證1/QPS秒內不允許請求進入.比如QPS=5,如果我們保證最后一個被授權請求之后的200ms的時間內沒有請求被授權,那么我們就達到了預期的速率.如果一個請求現在過來但是最后一個被授權請求是在100ms之前,那么我們就要求當前這個請求等待100ms.按照這個思路,請求15個新令牌(許可證)就需要3秒。如果RateLimiter的一個被授權請求之前很長一段時間沒有被使用會怎么樣?這個RateLimiter會立馬忘記過去這一段時間的利用不足,而只記得剛剛的請求。

斷路器

  Hystrix[hɪst'rɪks]由Netflix開源的一個延遲和容錯庫,用於隔離訪問遠程系統、服務或者第三方庫,防止級聯失敗,從而提升系統的可用性、容錯性與局部應用的彈性,是一個實現了超時機制和斷路器模式的工具類庫。

  Hystrix主要提供4個功能:斷路器、隔離機制、請求聚合和請求緩存。

  • 斷路器(Circuit breaker)

  Hystrix Command請求后端服務失敗數量超過一定比例(默認50%), 斷路器會切換到開路狀態(Open). 這時所有請求會直接失敗而不會發送到后端服務. 斷路器保持在開路狀態一段時間后(默認5秒), 自動切換到半開路狀態(HALF-OPEN). 這時會判斷下一次請求的返回情況, 如果請求成功, 斷路器切回閉路狀態(CLOSED), 否則重新切換到開路狀態(OPEN).

  • 隔離機制(Bulkheads)

  線程池隔離模式:使用一個線程池來存儲當前的請求,線程池對請求作處理,設置任務返回處理超時時間,堆積的請求堆積入線程池隊列。這種方式需要為每個依賴的服務申請線程池,有一定的資源消耗,好處是可以應對突發流量(流量洪峰來臨時,處理不完可將數據存儲到線程池隊里慢慢處理)

  信號量隔離模式:使用一個原子計數器(或信號量)來記錄當前有多少個線程在運行,請求來先判斷計數器的數值,若超過設置的最大線程個數則丟棄該類型的新請求,若不超過則執行計數操作請求來計數器+1,請求返回計數器-1。這種方式是嚴格的控制線程且立即返回模式,無法應對突發流量(流量洪峰來臨時,處理的線程超過數量,其他的請求會直接返回,不繼續去請求依賴的服務)

  • 請求聚合

  使用HystrixCollapser將前端的多個請求聚合成為一個請求發送到后端

  • 請求緩存

  HystrixCommand和HystrixObservableCommand實現了對請求的緩存,假如在某個上下文中有多個同時到達的相同參數的查詢,利用請求緩存功能,可以減少對后端系統的壓力。

超時與重試

  在微服務系統中,如果上游應用沒有設置合理的超時和重試機制,則會造成請求響應變慢,慢請求會積壓並耗盡系統資源。超時機制應該和限流、斷路器配合使用,最終實現微服務系統的穩定性。

 

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

高並發

  幾種常見的高並發策略如下:

  • 異步:提高業務過程中可異步部分的占比,提高異步部分的執行效率
  • 緩存:將頻繁訪問的數據存儲在離業務處理邏輯更近的地方
  • 池化:對於創建起來比較消耗資源的對象進行緩存

異步

  按照異步操作出現的位置,可用分為兩類:在JVM內部,使用異步線程池或者異步回調機制;在JVM外部,可用使用消息隊列、Redis隊列等中間件

  異步線程池

  Java中可用通過Executors和ThreadPoolExecutor方式創建線程池,通過Executors可用快速創建四種常見的線程池,但這種方式在實際使用中並不推薦,因為這種方式創建出來的線程池的可控性較差(FixedThreadPool和SingleThreadPool:允許的請求隊列長度為Integer.MAX_VALUE,可能對堆積大量請求,從而導致OOM;CacheThreadPool和ScheduledThreadPool:允許創建線程數量為Integer.MAX_VALUE,可能創建大量線程,從而導致OOM)。而通過ThreadPoolExecutor的方式去創建,可用讓開發人員更明確線程池的運行規則,避免資源耗盡的風險。同時可用實現自定義的拒絕策略,從而打印告警日志,並根據日志監控線程池的運行情況,在發生異常時及時處理。

  異步回調機制

  異步回調與同步調用的不同之處在於,請求發起方不需要等待服務方的響應返回,可用先去做別的業務。接口請求返回后會自動調用預先定義的回調函數,進行后續的業務處理。

  消息隊列

  消息隊列是系統架構層面的異步策略,應用場景很廣泛,如削峰填谷。典型應用就是優惠券發放和電商秒殺系統

緩存

  

  在分布式系統中,緩存無處不在。從緩存靜態資源的CDN,到緩存http請求的nginx,從瀏覽器或App客戶端的緩存,到服務端到數據存儲的緩存,不一而足。常見的分布式緩存中間件有Redis、Memcache等。在分布式系統中使用緩存時,還需要處理好緩存穿透、緩存雪崩、大value緩存監測、熱點緩存等問題。

 

  緩存穿透:一般的緩存系統都是按照key去緩存查詢的,如果不存在則去后端系統查找。如果key對應的value一定不存在,並且對該key的並發請求量很大,就會對后端系統造成很大的壓力。

  緩存雪崩:當緩存服務器重啟或者大量緩存集中在某一個時間段消失,在消失的這段時間,也會對后端系統帶來很大壓力

 

  

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM