前言
對於運行中的系統,可以說百分百的小伙伴會經常遇見以下問題:
- 網絡不通,突然又好了;
- 服務器宕機了;
- 調用服務接口超時了;
- 調用接口報錯啦;
- 通訊信息發送失敗需要重發;
以上只是列舉了一些常遇到的問題,對於一些小項目可能簡單的處理一下就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綜藝圈",跟我一起學~~~