前情提要
筆者在公司負責的系統是跟第三方串接有關的系統,因此經常要串接第三方的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的出現,藉由這篇來了解一下,我們下篇見了。
參考