# Polly ## 新手入門 ## Polly 是什麼 > Polly is a .NET resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, Rate-limiting and Fallback in a fluent and thread-safe manner. Google 翻譯告訴我,它是... > Polly 是一個 .NET 彈性和瞬態故障處理庫,允許開發人員以流暢和線程安全的方式表達重試、斷路器、超時、隔板隔離、速率限制和回退等策略。 總結一下,它能幫我們做什麼 ? 1. 簡單的Retry策略 2. 斷路器 3. 限速器 4. 控制Thread數量 5. Cache 6. FallBack策略 7. ..... ### 第一次不通,那可以打第二次、第三次阿 (Retry) 有些Api的是允許Retry的,如果說第一次打不通,那可以試試看打第二次,這時候會用到Retry這個特性 ``` var asyncRetryPolicy = Policy.Handle<Exception>() .OrResult<HttpResponseMessage>(x => x.IsSuccessStatusCode) .RetryAsync(retryCount: 3, (onRetry: delegatedResult, retryCount, context) => { context["RetryCount"] = retryCount; }); var httpResponseMessage = await asyncRetryPolicy .ExecuteAsync(async context => { var retryCount = (int)context["RetryCount"]; //// Call Api and return HttpResponseMessage }, new Context { ["RetryCount"] = 0 }); ``` ### 另外一種Retry,過幾秒再問 (Wait And Retry) ``` var asyncRetryPolicy = Policy.Handle<Exception>() .OrResult<HttpResponseMessage>(x => x.IsSuccessStatusCode) .WaitAndRetryAsync(retryCount: 3, sleepDurationProvider: currentCount => TimeSpan.FromSeconds(currentCount), onRetry: (delegatedResult, timeSpan, context) => { //// do something }); ``` ### 對接Api壞掉了😢 (Circuit-breaker) 如果對接Api壞掉了,那我們是不是可以過段時間再問問 ? ``` Policy.Handle<Exception>() .CircuitBreakerAsync(exceptionsAllowedBeforeBreaking: 2, durationOfBreak: TimeSpan.FromSeconds(2), onBreak: (exception, timespan) => { //// Do something when circuit break }, onReset: () => { //// Do something when circuit reset }); ``` ### 不要打太快 (Rate-limit) ``` Policy.RateLimitAsync<HttpResponseMessage>( numberOfExecutions: 5, perTimeSpan: TimeSpan.FromSeconds(3), maxBurst: 5); ``` ### 同時最高執行數量 (Bulkhead Isolation) ``` Policy.BulkheadAsync<HttpResponseMessage>( maxParallelization: 5, maxQueuingActions: 2, onBulkheadRejectedAsync: context => { //// Do Something }); ``` ### Cache (Cache) ``` var asyncCachePolicy = Policy .CacheAsync<HttpResponseMessage>(cacheProvider: memoryCacheProvider, ttl: TimeSpan.FromMinutes(5), onCacheError: (context, key, ex) => { //// Do something when Cache Error }); var httpResponseMessage = await asyncCachePolicy .ExecuteAsync(context => { //// Do something }, new Context("OpenDataKey")); ``` ### 錯誤處理 (Fallback) ``` Policy<HttpResponseMessage> .Handle<Exception>() .OrResult(x => x.IsSuccessStatusCode == false) .FallbackAsync(fallbackAction: cancellationToken => { //// Do something }, onFallbackAsync: delegatedResult => { //// Do something }); ``` ### 同時需要好幾個特性 (PolicyWrap) ``` Policy.WrapAsync( Policy.CacheAsync<HttpResponseMessage>( cacheProvider: new Extension.MemoryCacheProvider(new MemoryCache(new MemoryCacheOptions())), ttl: TimeSpan.FromSeconds(5)), Policy<HttpResponseMessage>.Handle<Exception>() .RetryAsync(retryCount: 3, onRetry: (_, retryCount, context) => { //// Do something }) ); ```