前言
對於執行中的系統,可以說百分百的小夥伴會經常遇見以下問題:
- 網路不通,突然又好了;
- 伺服器當機了;
- 呼叫服務介面超時了;
- 呼叫介面報錯啦;
- 通訊資訊傳送失敗需要重發;
以上只是列舉了一些常遇到的問題,對於一些小專案可能簡單的處理一下就OK了(比如重啟或是重新發布),而對於微服務架構的專案,可能因為一個服務掛掉、或是一臺伺服器當機、又或是網路出現波動等情況,都可能會導致業務流程失敗,甚至會導致整個系統崩掉。所以對於系統瞬時故障需及時做出應對策略,對於可能會發生的故障需提前預防(彈性應變);Polly這個庫針對以上等情況進行封裝,通過策略的方式,靈活處理相關場景。
正文
1. 簡介
Polly是一種.NET彈性和瞬態故障處理庫,可以通過不同策略處理和應對故障場景,主要分為兩大類:被動策略和主動策略,各自包含如下功能:
1.1 被動策略
主要針對故障的處理,避免如下:
- 重試(Retry):在實際應用場景中往往有些失敗只是瞬時的,經過短暫的延時就可恢復,這種情況就可以採用重試策略;
- 熔斷(Circuit Breaker):比如在呼叫介面發生異常時,當多次都返回異常,建議先熔斷一段時間,即不再處理業務介面,直接報錯;待熔斷時間過了之後可以重新處理請求,即快速響應失敗比讓使用者一直等待要合理;
- 回退(Fallback):如果失敗之後怎麼處理?即在發生故障的時候找一個替代邏輯進行處理, 比如返回指定的結果或是進行下一步操作;
1.2 主動策略
主要是進行彈性擴充套件,而不是針對故障處理,關鍵點是改變原有業務邏輯的執行行為,比如原業務邏輯超時了,就會執行指定的超時處理行為;
- 超時(Timeout ):確保呼叫者永遠不需要等待超過配置的超時時間,不然就會觸發超時異常;主要就是為了提升使用者體驗;
- 艙壁隔離(Bulkhead Isolation):即一個服務的故障不應該影響到整個系統(隔離);通過控制資源消耗,避免一個故障導致級聯服務也故障,最終影響整個系統;目的就是進行併發控制(限流),避免故障帶來的大範圍影響。
- 快取(Cache):將資料存入快取中,後續的響應可以從快取中獲取; 目的就是為了提升效能;
- 策略包裝( PolicyWrap):策略可以組合進行使用;目的就是為了方便各種策略組合進行業務故障處理;
大概理解Polly功能之後,接下來就通過Demo的形式進一步瞭解各策略的使用;
2. 功能Demo演示
Polly使用步驟很簡單,兩個步驟完事:
- 定義策略;
- 執行策略;
以下的各功能的演示,主要體現的是用法,不會所有情況都舉例演示,僅提供思路;其中說明主要結合程式碼,以註釋為主:
2.1 重試(Retry)
程式碼實現:
執行結果(測試的時候,用Release模式或者直接執行編譯後的執行檔案,不然Debug模式的時候遇見異常會提示,檢視結果不方便):
上面邏輯是失敗就重試,其實在實際應用場景,通常有一個時間間隔重試,每次重試遞增的時間不一樣,程式碼如下:
執行結果如下:
2.2 熔斷(Circuit Breaker)
程式碼實現:
執行結果:
上面這種只是常規熔斷方式,Polly還提供高階熔斷配置,根據熔斷比率進行熔斷,更加符合應用場景,通過設定樣本收集時間,然後計算收集的業務處理結果比率,如果達到熔斷比率就進行熔斷。程式碼如下:
執行效果如下:
2.3 回退(Fallback)
程式碼實現如下:
執行結果:
當異常發生的時候,也可以指定對應的操作邏輯。
2.4 超時(Timeout )
程式碼實現:
執行結果:
超時這分為樂觀超時(Optimistic timeout)和悲觀超時(Pessimistic timeout),樂觀超時需要CancellationToken 在業務邏輯中進行取消,而悲觀超時沒有取消的話,超時了還會繼續執行,上面的案例就顯示了,當觸發超時之後,業務邏輯等待一段時間之後,還會返回結果,這個過程是需要耗費相關效能的;根據需要可以自行選擇。樂觀超時就不演示了,和正常執行緒邏輯一樣,通過CancellationToken取消即可。
超時策略的最終目的就是考慮到使用者體驗,及時給使用者反饋,不讓使用者一直處於等待中~~~~
2.5 艙壁隔離(Bulkhead Isolation)
程式碼實現:
執行效果:
其實在設定策略引數的時候,還可以指定等待佇列的數,也就是說當業務執行數達到設定併發數時,還可以繼續執行業務,只是這些業務先會進入等待佇列中;這裡就不詳細演示了,後續在API中在具體說明,對於限流這塊,放在API那塊可能更容易理解,這裡就先進了解。
2.6 快取(Cache)
快取這塊演示的是基於記憶體的,需要額外引入包Polly.Caching.Memory和Microsoft.Extensions.Caching.Memory,關於MemoryCache的具體細節,可以參考這篇文章(因MemoryCache鬧了個笑話)。
程式碼實現:
執行效果:
關於快取這塊,也是可以整合Redis進行做分散式快取的。後面的專案分享的時候再詳細說,如果小夥伴好奇,可以參照官網,用法和上面一樣,只是引用的包不一樣而已。
2.7 策略包裝( PolicyWrap)
程式碼及執行效果:目的就是為了組合策略,應對業務邏輯的各種情況。
上述只是演示了常用的策略使用方式,並沒有面面俱到,更加詳細內容可以參照官網,結合我的演示思路,看官網例子就很容易啦:
官網地址:https://github.com/App-vNext/Polly/wiki/PolicyWrap
總結
關於Polly,就先說到這,後面的Demo或專案中肯定還會用到的,在這裡用控制檯專案的方式演示,一方面是為了方便,針對某個點好測試,另一方面是為了說明Polly不是針對WebAPI呼叫採用的,而是根據需要在專案其他任何地方都可以用(好多小夥伴都認為只是用於HttpClient呼叫API);
Polly瞭解大概情況之後,下期繼續接著閘道器(Ocelot)剩下的功能進行分享~~~
一個被程式搞醜的帥小夥,關注"Code綜藝圈",跟我一起學~~~