.Net Core 之 Polly 策略

Polly 是一個 .NET 彈性和瞬態故障處理庫,允許開發人員以流暢和線程安全的方式表達重試、斷路器、超時、隔板隔離、速率限制和回退等策略。

查看源碼或者一些基礎用法點擊瞭解詳情, 如果想更深入的瞭解,點擊進入官網。

polly提供的幾種彈性策略:

 

普通用法

引用NuGet包:

Install-Package Polly

 悲觀超時(TimeoutStrategy.Pessimistic),依然會返回結果

int res = 0;
var testPolicy = Policy.Timeout(5, TimeoutStrategy.Pessimistic, (context, timespan, task) =>
{
    res = 1;
    Console.WriteLine("你已經超時了");
});

try
{
    testPolicy.Execute(() =>
    {
        Console.WriteLine("開始執行方法");
        Thread.Sleep(10000);
        Console.WriteLine("執行結束了");
        res = 2;
    });
}
catch (Exception ex)
{
    Console.WriteLine("異常了");
}
Console.WriteLine("最後的結果是:" + res);
View Code

樂觀超時(TimeoutStrategy.Optimistic),不會返回結果

var testPolicy = Policy.TimeoutAsync(5, TimeoutStrategy.Optimistic, (context, timespan, task) =>
{
    Console.WriteLine("你已經超時了");
});
try
{
    var str = testPolicy.ExecuteAsync<string>((cancel) =>
    {
        //如果5秒鐘超時會觸發
        cancel.Register(() => {

            Console.WriteLine("你已經超時了 ");
        });
        Console.WriteLine("開始執行方法");
        Thread.Sleep(1000);
        Console.WriteLine("執行結束了");
        return Task.FromResult(res.ToString());
    }, CancellationToken.None);
}
catch (Exception ex)
{
    Console.WriteLine("異常了");
}
View Code

重試

try
{
    var policy = Policy.Handle<Exception>().Retry(5, (exception, count, context) =>
    {
        Console.WriteLine($"第{count}次異常,異常信息:{exception.Message}");
    });
    Console.WriteLine("開始執行");
    policy.Execute(() =>
    {
        throw new Exception("我異常了");
    });
}
catch (Exception ex)
{
    Console.WriteLine("進入最後的異常了");
}
View Code

重試等待

try
{
    var policy = Policy.Handle<Exception>().WaitAndRetryAsync(5,
        (count) => {
            //每次等待時間一致
            //return TimeSpan.FromSeconds(5);
            //根據次數等待時間不一樣
            return TimeSpan.FromSeconds(5 * count);
        },
        (exception,timespan, count, context) =>
        {
            Console.WriteLine($"第{count}次異常,等待時間:{timespan.TotalSeconds},異常信息:{exception.Message}");
        });
    Console.WriteLine("開始執行");
    await policy.ExecuteAsync(() =>
    {
        throw new Exception("我異常了");
    });
}
catch (Exception ex)
{
    Console.WriteLine("進入最後的異常了");
}
View Code

熔斷

try
{
    //如果10秒內異常達到2次,則觸發熔斷,10秒之內不會訪問方法體,只會返回熔斷異常,10秒之後纔會請求方法體
    var policy = Policy.Handle<Exception>().CircuitBreakerAsync(2,TimeSpan.FromSeconds(10),
        (exception, timespan) => {
            Console.WriteLine($"開始等待:{timespan.TotalSeconds} s, 異常信息:{exception.Message}");
        },
        //如果等待10秒鐘之後可以正常訪問就會觸發
        () =>
        {
            Console.WriteLine("熔斷重置");
        },
        //每隔10秒鐘觸發
        () => {
            Console.WriteLine("正在打開或者關閉熔斷");
        }
        );
    Console.WriteLine("開始執行");
    for (int i = 0; i < 20; i++)
    {
        Thread.Sleep(1000);
        try
        {
            await policy.ExecuteAsync(() =>
            {
                throw new Exception("我異常了");
            });
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

    }

}
catch (Exception ex)
{
    Console.WriteLine("進入最後的異常了");
}
View Code

降級

try
{
    //如果10秒內異常達到2次,則觸發熔斷,10秒之內不會訪問方法體,只會返回熔斷異常,10秒之後纔會請求方法體
    var policy = Policy<string>.Handle<Exception>().FallbackAsync((context,token) => {
        return Task.FromResult("降級異常");
    }, (exception, context) => {
        return Task.FromResult("降級異常2");
    });
    Console.WriteLine("開始執行");
    var res =  await policy.ExecuteAsync(() =>
    {
        throw new Exception("我異常了");
    });
    Console.WriteLine(res);
}
catch (Exception ex)
{
    Console.WriteLine("不會進入這個異常");
}
View Code

請求限速

try
{
    var rateLimit = Policy.RateLimit(2, TimeSpan.FromSeconds(1),6);

    for (int a = 0; a < 10; a++)
    {
        Thread.Sleep(500);
        for (int i = 0; i < 500; i++)
        {
            rateLimit.Execute(() => {
                Console.WriteLine("執行");
            });
        }
    }

}
catch (RateLimitRejectedException ex)
{
    Console.WriteLine("策略異常" + ex.Message);
}
View Code

 

在HttpClient拓展

引用NuGet包:

Install-Package Polly
Install-Package Microsoft.Extensions.Http.Polly

 

// 1、自定義異常處理(用緩存處理)
var fallbackResponse = new HttpResponseMessage
{
    Content = new StringContent("系統正繁忙,請稍後重試"),// 內容,自定義內容
    StatusCode = HttpStatusCode.BadRequest // 定義返回的StatusCode
};

services.AddHttpClient("mrico")
    // 1.1 降級(捕獲異常,進行自定義處理)
    .AddPolicyHandler(Policy<HttpResponseMessage>.Handle<Exception>().FallbackAsync(fallbackResponse, async b =>
                {
                    // 1、降級打印異常
                    Console.WriteLine($"開始降級,異常消息:{b.Exception.Message}");
                    // 2、降級後的數據
                    //Console.WriteLine($"降級內容響應:{}");
                    await Task.CompletedTask;
                }))
    // 1.2 熔斷機制
    .AddPolicyHandler(Policy<HttpResponseMessage>.Handle<Exception>().CircuitBreakerAsync(3, TimeSpan.FromSeconds(10), (ex, ts) =>
                {
                    Console.WriteLine($"斷路器開啓,異常消息:{ex.Exception.Message}");
                    Console.WriteLine($"斷路器開啓時間:{ts.TotalSeconds}s");
                }, () =>
    {
        Console.WriteLine($"斷路器重置");
    }, () =>
    {
        Console.WriteLine($"斷路器半開啓(一會開,一會關)");
    }))
     // 1.3 失敗重試
     .AddPolicyHandler(Policy<HttpResponseMessage>
            .Handle<Exception>()
            .WaitAndRetryAsync(50, (trycount) =>
            {
                return TimeSpan.FromSeconds(2 * trycount); //每次等待的時間
            }))
    //1.4、超時
    .AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(2), TimeoutStrategy.Pessimistic, (context, timespan, task) => {
            return Task.FromResult(fallbackResponse);
          }));
View Code

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章