前情提要
筆者在公司負責的系統是跟第三方串接有關的系統,因此經常要串接第三方的API
,WebServie
,Dll
等串接方式,若是API(Http Request)
串接則,筆者這邊都全面改用Refit
來串接,好處就不再贅述了,即便透過Refit
來發Http Request
,原本的DotnetCore
預設的HttpClient
相關的延伸應用,皆可延續使用,以此篇主題來說,筆者這邊想使用Polly
做Retry
的機制,讓我們繼續看下去。
內容
筆者這邊對多個第三方串接的經驗來說,HttpRequest
發出時的驗證,大概就遇過以下幾類
- 定義好的
SecretKey
或其他設定值透過Header
特定Key
設定上去 - 以第一種設定之外,有些第三方,還會有加密
Request Body
後塞在某一個HeaderKey
上以驗證封包正確性 - 有獨立
Api
可以取得AccessToken
,並在每個ApiRequest
上的Authorization Header
上設定其取得的AccessToken
以獨立取得AccessToken
來說,因Http
連線成本比較高,若允許使用Redis
的狀況下,就可以考慮將取得的AccessToken
存於Redis
上,並將過期時間設定為取得AccessToken
時拿到的ExpireTime
往Redis
設定ExpireTime
。所以會變成會先檢查Redis上面有無對應的AccessToken
,有則直接取得並設定於AuthorizationHeader
中,若無,則打一次取得AccessToken
的API
,將結果設定於Redis
中,以便之後的Request
取用。
但畢竟不是自己的系統,以筆者經驗來說,因時間差或第三方系統問題等等,在Redis
上面的值尚未到期之前,還是有機會收到401
,若沒有任何處理,可能都會以Redis
上的AccessToken
往第三方做驗證,止到Redis
上面的ExpireTime
到期為止,總不可能讓系統無法運作,還是想些辦法來解決這個問題。
筆者的思考脈絡就是,既然系統是靠Redis
來決定要不要打取得AccessToken
的API
,就在Redis
上動手腳,搭配Polly
上的設定,收到401
時的行為如下
- 將
Redis
上的值刪除 - 重試一次
- 重發一次
HttpRequest
,這時Redis
上的值被刪除,因此會再打一次取得AccessToken
的API
,將最新的AccessToken
設定於Redis
中
- 重發一次
以上兩步驟就能徹底解決問題
客製HttpMessageHandler
透過HttpMessageHandler
,遇到401
時將Redis
上的值刪除
1 | public class UnAuthorizeHttpMessageHandler : MyHttpMessageHandler |
上面出現的MyHttpMessageHandler
為上幾篇有介紹到,需要的朋友請參考 [DotnetCore]Refit:HttpMessageHandler應用
Polly套用
這個部份已被微軟整合進http
相關套件中,我們只要安裝Microsoft.Extensions.Http.Policy
即可,宣告一下對應的retry
機制
1 | var retryPolicy = HttpPolicyExtensions |
註冊Refit
透過Refit
宣告時將上面宣告好的Retry Policy
掛到refit
的設定中即可
- 首先安裝
Microsoft.Extensions.Http.Polly
這個nuget
套件 - 接在
AddRefitClient
後面即可,ExtensionMethod
為AddPolicyHandler
1 | services.AddRefitClient<ITestApiRepository>() |
結論
藉由這篇來介紹一下Polly
於HttpRequest
時的應用,若需要判定HttpResponse
的StatusCode
要做一些重試的動作,不妨可以試試搭配Polly
的RetryPolicy
,設定上也方便,與主邏輯也分開,各司其職,肯定比自己手刻的Retry
機制好,也比較不會有無法預測的SideEffect
的出現,藉由這篇來了解一下,我們下篇見了。
參考