Polly簡單使用

簡介

Polly 是一個針對 .NET 應用程序的庫,提供了一系列經過優化的故障處理策略,幫助開發人員實現重試、斷路器、超時和熔斷機制等。通過 Polly 庫,開發人員可以更容易地編寫魯棒性更強、更可靠的應用程序。

Retry 策略

當出現異常或錯誤時,自動重試指定次數。

static void Main()
{
	try
	{
		//捕獲DivideByZeroException異常會重試三次
		var retryTwoTimesPolicy =
			 Policy
				//處理多個異常類型通過OR即可
				 .Handle<DivideByZeroException>().Or<ArgumentException>()
				 .Retry(3, (ex, count) =>
				 {
					 Console.WriteLine("執行失敗! 重試次數 {0}", count);
					 Console.WriteLine("異常來自 {0}", ex.GetType().Name);
				 });
		retryTwoTimesPolicy.Execute(() =>
		{
			var a = 0;
			return 1 / a;
		});
	}
	catch (Exception ex)
	{
		//第四次異常不做處理,拋出異常
		Console.WriteLine($"catch {ex.GetType().Name}");
	}
	finally
	{
		Console.WriteLine($"finally");
	}
}

image

static void Main()
{
	try
	{
		//捕獲DivideByZeroException異常會重試三次
		var retryTwoTimesPolicy =
			 Policy
				 //處理多個異常類型通過OR即可
				 .Handle<DivideByZeroException>().Or<ArgumentException>()
				 //添加重新間隔
				 .WaitAndRetry(new[]
				 {
						TimeSpan.FromSeconds(1),
						TimeSpan.FromSeconds(3),
						TimeSpan.FromSeconds(5),
				 }, (ex, TimeSpan) =>
				 {
					 Console.WriteLine($"執行失敗! 執行間隔 {TimeSpan} {DateTime.Now}");
					 Console.WriteLine($"異常來自 {ex.GetType().Name}");
				 });

				retryTwoTimesPolicy.Execute(() =>
				{
					var a = 0;
					return 1 / a;
				});
	}
	catch (Exception ex)
	{
		Console.WriteLine($"catch {ex.GetType().Name}");
	}
	finally
	{
		Console.WriteLine($"finally");
	}
}

image

Timeout 策略

在規定時間內未獲取到響應時,自動取消請求並拋出超時異常。

static async Task Main()
{

	// 創建超時策略,等待最多 1 秒鐘
	// 如果在等待時間內未完成操作,則會拋出 TimeoutRejectedException 異常。
	var timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromSeconds(1), TimeoutStrategy.Pessimistic);

	try
	{
		// 在超時策略中執行操作
		await timeoutPolicy.ExecuteAsync(async (ct) =>
		{
			using (HttpClient httpClient = new HttpClient())
			{
				var response = await httpClient.GetAsync("https://www.example.com", ct);

				// 處理響應結果
				response.EnsureSuccessStatusCode();
				var content = await response.Content.ReadAsStringAsync(ct);
				Console.WriteLine(content);
			}
		}, CancellationToken.None);
		/*
		 * 最後,我們使用 ExecuteAsync 方法,在組合策略中執行異步操作,並在 CancellationToken 參數中傳遞 CancellationToken.None 來允許取消操作。
		 * 如果在指定的等待時間內沒有得到響應,則會拋出 TimeoutRejectedException 異常。如果操作失敗,則會捕獲異常並輸出相應的信息。
		 */

	}
	catch (TimeoutRejectedException)
	{
		Console.WriteLine("The operation timed out.");
	}
	catch (Exception ex)
	{
		Console.WriteLine($"Exception caught: {ex.GetType().Name}");
	}
}

image

Circuit Breaker 策略

當某個遠程服務發生異常或錯誤時,自動跳閘斷路,避免進一步請求對該服務造成負載壓力和損害。

static async Task Main()
{
	//連續失敗 5 次,那麼斷路器會被打開,並保持 5 秒鐘的打開狀態時間,防止繼續執行相同的操作
	var circuitBreakerPolicy = Policy
		.Handle<Exception>()
		.CircuitBreaker(5, TimeSpan.FromSeconds(5));

	// 對多個操作使用相同的斷路器策略
	for (int i = 0; i < 20; i++)
	{
		try
		{
			await Task.Delay(TimeSpan.FromSeconds(1));
			// 嘗試執行某些可能會拋出異常的操作
			circuitBreakerPolicy.Execute(() =>
			{
				// TODO: 執行某些操作,可能會拋出異常
				throw new Exception($"異常");
			});
		}
		catch (Exception ex)
		{
			// 斷路器開啓,操作被拒絕
			Console.WriteLine($"time:{DateTime.Now} Num:{i} failed: {ex.Message}");
		}
	}
}

image

Microsoft.Extensions.Http.Polly

是基於 Polly 的一個 ASP.NET Core HttpClient 工廠的擴展庫,它能夠爲應用程序提供簡單易用的、可擴展的 HTTP 客戶端工廠,並且可以很容易地實現重試、熔斷、超時等策略。

var retryPolicy = HttpPolicyExtensions
   .HandleTransientHttpError()
   .Or<TimeoutRejectedException>() // thrown by Polly's TimeoutPolicy if the inner execution times out
   .RetryAsync(3);

var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(10);
//更方便的使用polliy
services.AddHttpClient("example.com", c => c.BaseAddress = new Uri("http://example.com"))
	  .AddPolicyHandler(retryPolicy)
	  .AddPolicyHandler(timeoutPolicy);

參考

https://github.com/App-vNext/Polly
https://github.com/App-vNext/Polly.Extensions.Http/blob/master/README.md

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