Polly Retry(對於開發者的運行原理)
優雅地處理暫態故障、逾時和異常對建立穩健且有彈性的應用程式至關重要。 Polly 是一個廣受歡迎的 .NET 函式庫,提供彈性和暫態故障處理功能。 在其眾多功能中,"重試"是使用最廣泛的政策之一。
在這篇文章中,我們將深入探討 Polly 的 C# 重試原則,探索其用法和組態選項,並提供實用的程式碼範例。 此外,我們將使用 IronPDF Library for PDF Generation 與 Polly Retry 嘗試產生 PDF 的表單請求結果。
什麼是 Polly Retry?
Polly Retry 是 Polly 函式庫所提供的一項政策,可讓開發人員自動重試可能因錯誤或瞬間故障而失敗的作業。 暫態故障是指由於網路故障、服務無法提供或其他暫態問題而發生的暫時錯誤。
透過 Polly 的重試政策,您可以定義重試作業的規則,包括重試的最大次數、多次重試之間的延遲時間,以及重試失敗請求的條件。這有助於建立有彈性的應用程式,可從暫時的故障中恢復,而不會當機或對終端使用者造成干擾。
開始使用 Polly Retry
在深入了解程式碼範例之前,讓我們先建立一個基本的了解,如何在 C# 專案中安裝和設定 Polly。
安裝 Polly
您可以使用下列指令透過 NuGet 套件管理員控制台安裝 Polly:
Install-Package Polly
或透過 .NET CLI:
dotnet add package Polly
新增 Polly 使用語句
在您的 C# 檔案中,包含 Polly 命名空間:
using Polly;
using Polly;
Imports Polly
基本重試原則範例
讓我們從一個簡單的範例開始,重試模擬從遠端服務取得資料的作業。我們將設定一個重試原則,最多重試 3 次,重試之間的固定超時延遲為 2 秒。
using System;
using System.Net.Http;
using Polly;
namespace PollyRetryExample
{
public class Program
{
public static void Main(string[] args)
{
// Define a retry policy that handles HttpRequestException with a maximum of 3 retries
var retryPolicy = Policy
.Handle<HttpRequestException>() // Specify the exception type to handle
.WaitAndRetry(
3, // Max retry attempts
retryAttempt => TimeSpan.FromSeconds(2), // Fixed retry delay
(exception, timeSpan, retryCount, context) =>
{
Console.WriteLine("Retry {0} due to {1}", retryCount, exception.Message);
});
try
{
// Execute the action within the context of the retry policy
retryPolicy.Execute(() =>
{
FetchDataFromRemoteService();
});
}
catch (Exception ex)
{
Console.WriteLine("Failed after 3 retries: {0}", ex.Message);
}
}
// Simulate fetching data that throws HttpRequestException
public static void FetchDataFromRemoteService()
{
throw new HttpRequestException("Failed to fetch data from remote service");
}
}
}
using System;
using System.Net.Http;
using Polly;
namespace PollyRetryExample
{
public class Program
{
public static void Main(string[] args)
{
// Define a retry policy that handles HttpRequestException with a maximum of 3 retries
var retryPolicy = Policy
.Handle<HttpRequestException>() // Specify the exception type to handle
.WaitAndRetry(
3, // Max retry attempts
retryAttempt => TimeSpan.FromSeconds(2), // Fixed retry delay
(exception, timeSpan, retryCount, context) =>
{
Console.WriteLine("Retry {0} due to {1}", retryCount, exception.Message);
});
try
{
// Execute the action within the context of the retry policy
retryPolicy.Execute(() =>
{
FetchDataFromRemoteService();
});
}
catch (Exception ex)
{
Console.WriteLine("Failed after 3 retries: {0}", ex.Message);
}
}
// Simulate fetching data that throws HttpRequestException
public static void FetchDataFromRemoteService()
{
throw new HttpRequestException("Failed to fetch data from remote service");
}
}
}
Imports System
Imports System.Net.Http
Imports Polly
Namespace PollyRetryExample
Public Class Program
Public Shared Sub Main(ByVal args() As String)
' Define a retry policy that handles HttpRequestException with a maximum of 3 retries
Dim retryPolicy = Policy.Handle(Of HttpRequestException)().WaitAndRetry(3, Function(retryAttempt) TimeSpan.FromSeconds(2), Sub(exception, timeSpan, retryCount, context)
Console.WriteLine("Retry {0} due to {1}", retryCount, exception.Message)
End Sub)
Try
' Execute the action within the context of the retry policy
retryPolicy.Execute(Sub()
FetchDataFromRemoteService()
End Sub)
Catch ex As Exception
Console.WriteLine("Failed after 3 retries: {0}", ex.Message)
End Try
End Sub
' Simulate fetching data that throws HttpRequestException
Public Shared Sub FetchDataFromRemoteService()
Throw New HttpRequestException("Failed to fetch data from remote service")
End Sub
End Class
End Namespace
在這個範例中
Handle<HttpRequestException>()指定我們要處理HttpRequestException,如果發生這種情況,則重試操作。WaitAndRetry()配置重試策略,重試次數為 3 次,重試之間固定延遲 2 秒(指定最大持續時間)。onRetry代理程式在重試發生時記錄訊息。

進階重試原則設定
指數退避
Exponential backoff 是一種流行的重試策略,其中請求與重試之間的延遲會以指數方式增加。 Polly 提供了一種使用 WaitAndRetry() 實現指數退避的便捷方法。
var retryPolicy = Policy
.Handle<HttpRequestException>()
.WaitAndRetry(
retryCount: 3, // Max retry attempts
sleepDurationProvider: attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)), // Exponential delay
onRetry: (exception, timeSpan, retryCount, context) =>
{
Console.WriteLine($"Retry {retryCount} due to {exception.Message}");
});
var retryPolicy = Policy
.Handle<HttpRequestException>()
.WaitAndRetry(
retryCount: 3, // Max retry attempts
sleepDurationProvider: attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)), // Exponential delay
onRetry: (exception, timeSpan, retryCount, context) =>
{
Console.WriteLine($"Retry {retryCount} due to {exception.Message}");
});
Dim retryPolicy = Policy.Handle(Of HttpRequestException)().WaitAndRetry(retryCount:= 3, sleepDurationProvider:= Function(attempt) TimeSpan.FromSeconds(Math.Pow(2, attempt)), onRetry:= Sub(exception, timeSpan, retryCount, context)
Console.WriteLine($"Retry {retryCount} due to {exception.Message}")
End Sub)

使用斷路器重試
將重試與斷路器結合,可以在服務持續失敗時防止重複重試,進而進一步提升彈性。 Polly 可讓您輕鬆結合重試與斷路策略。
// Define a circuit breaker policy
var circuitBreakerPolicy = Policy
.Handle<HttpRequestException>()
.CircuitBreaker(
exceptionsAllowedBeforeBreaking: 3, // Number of exceptions before breaking
durationOfBreak: TimeSpan.FromSeconds(30), // Time circuit stays open
onBreak: (ex, breakDelay) =>
{
Console.WriteLine($"Circuit broken due to {ex.Message}. Retry after {breakDelay.TotalSeconds} seconds.");
},
onReset: () =>
{
Console.WriteLine("Circuit reset.");
});
// Define a retry policy
var retryPolicy = Policy
.Handle<HttpRequestException>()
.WaitAndRetry(
retryCount: 3, // Max retry attempts
sleepDurationProvider: attempt => TimeSpan.FromSeconds(2), // Fixed retry delay
onRetry: (exception, timeSpan, retryCount, context) =>
{
Console.WriteLine($"Retry {retryCount} due to {exception.Message}");
});
// Combine both policies into a single policy wrap
var policyWrap = Policy.Wrap(circuitBreakerPolicy, retryPolicy);
// Define a circuit breaker policy
var circuitBreakerPolicy = Policy
.Handle<HttpRequestException>()
.CircuitBreaker(
exceptionsAllowedBeforeBreaking: 3, // Number of exceptions before breaking
durationOfBreak: TimeSpan.FromSeconds(30), // Time circuit stays open
onBreak: (ex, breakDelay) =>
{
Console.WriteLine($"Circuit broken due to {ex.Message}. Retry after {breakDelay.TotalSeconds} seconds.");
},
onReset: () =>
{
Console.WriteLine("Circuit reset.");
});
// Define a retry policy
var retryPolicy = Policy
.Handle<HttpRequestException>()
.WaitAndRetry(
retryCount: 3, // Max retry attempts
sleepDurationProvider: attempt => TimeSpan.FromSeconds(2), // Fixed retry delay
onRetry: (exception, timeSpan, retryCount, context) =>
{
Console.WriteLine($"Retry {retryCount} due to {exception.Message}");
});
// Combine both policies into a single policy wrap
var policyWrap = Policy.Wrap(circuitBreakerPolicy, retryPolicy);
' Define a circuit breaker policy
Dim circuitBreakerPolicy = Policy.Handle(Of HttpRequestException)().CircuitBreaker(exceptionsAllowedBeforeBreaking:= 3, durationOfBreak:= TimeSpan.FromSeconds(30), onBreak:= Sub(ex, breakDelay)
Console.WriteLine($"Circuit broken due to {ex.Message}. Retry after {breakDelay.TotalSeconds} seconds.")
End Sub, onReset:= Sub()
Console.WriteLine("Circuit reset.")
End Sub)
' Define a retry policy
Dim retryPolicy = Policy.Handle(Of HttpRequestException)().WaitAndRetry(retryCount:= 3, sleepDurationProvider:= Function(attempt) TimeSpan.FromSeconds(2), onRetry:= Sub(exception, timeSpan, retryCount, context)
Console.WriteLine($"Retry {retryCount} due to {exception.Message}")
End Sub)
' Combine both policies into a single policy wrap
Dim policyWrap = Policy.Wrap(circuitBreakerPolicy, retryPolicy)
在這個範例中
CircuitBreaker()定義了一個斷路器策略,該策略在發生 3 次異常後斷開,並保持開啟 30 秒。Policy.Wrap()將斷路器和重試策略合併為一個策略。

IronPDF 簡介
IronPDF C# PDF Library Overview 是一個功能強大的 C# 函式庫,可讓開發人員在其 .NET 應用程式中建立、編輯和處理 PDF 文件。 無論您需要建立發票、報告或任何其他類型的 PDF 文件,IronPDF 都能提供直覺的 API,簡化流程。
使用 IronPDF,您可以輕鬆地將 HTML、CSS 甚至 ASP.NET 網頁轉換為 PDF,使其成為適用於各種應用程式的多功能工具。 此外,它還提供進階功能,例如在 PDF 中加入文字、圖片和互動元素,以及使用加密和數位簽章保護 PDF。
IronPDF 擅長於 HTML 至 PDF 的轉換,確保精確地保留原始版面與樣式。 它非常適合從網頁內容(如報告、發票和文件)產生 PDF。 IronPDF 支援將 HTML 檔案、URL 和原始 HTML 字串轉換為高品質的 PDF 檔案。
using IronPdf;
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
// 1. Convert HTML String to PDF
var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");
// 2. Convert HTML File to PDF
var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");
// 3. Convert URL to PDF
var url = "http://ironpdf.com"; // Specify the URL
var pdfFromUrl = renderer.RenderUrlAsPdf(url);
pdfFromUrl.SaveAs("URLToPDF.pdf");
}
}
using IronPdf;
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
// 1. Convert HTML String to PDF
var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");
// 2. Convert HTML File to PDF
var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");
// 3. Convert URL to PDF
var url = "http://ironpdf.com"; // Specify the URL
var pdfFromUrl = renderer.RenderUrlAsPdf(url);
pdfFromUrl.SaveAs("URLToPDF.pdf");
}
}
Imports IronPdf
Friend Class Program
Shared Sub Main(ByVal args() As String)
Dim renderer = New ChromePdfRenderer()
' 1. Convert HTML String to PDF
Dim htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>"
Dim pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent)
pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf")
' 2. Convert HTML File to PDF
Dim htmlFilePath = "path_to_your_html_file.html" ' Specify the path to your HTML file
Dim pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath)
pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf")
' 3. Convert URL to PDF
Dim url = "http://ironpdf.com" ' Specify the URL
Dim pdfFromUrl = renderer.RenderUrlAsPdf(url)
pdfFromUrl.SaveAs("URLToPDF.pdf")
End Sub
End Class
使用 IronPDF 重試。
在使用 IronPDF 時,可能會遇到需要從外部來源取得資料或在產生 PDF 之前執行複雜操作的情況。
在這種情況下,您可能會遇到可能導致 PDF 生成失敗的暫態故障或臨時問題。 要優雅地處理這些瞬間故障,您可以將 Polly Retry 與 IronPDF 配合使用。
安裝 IronPDF 和 Polly
在開始之前,請務必先在您的專案中安裝 IronPDF NuGet 套件。
Install-Package IronPdf
在 IronPDF 中使用 Polly Retry 。
讓我們來看看一個範例,在使用 IronPDF 產生 PDF 時,我們使用 Polly Retry 來處理暫態故障。 在以下範例中,我們將模擬從外部 API 取得資料,然後根據這些資料產生 PDF。 如果發生故障,我們將使用 Polly Retry 來執行資料擷取操作。
using System;
using System.Net.Http;
using System.Threading.Tasks;
using IronPdf;
using Polly;
namespace IronPdfWithPollyRetry
{
public class Program
{
public static async Task Main(string[] args)
{
// Define a retry policy with async capability
var retryPolicy = Policy
.Handle<HttpRequestException>() // Specify exception type to handle
.WaitAndRetryAsync(
3, // Retry attempts
retryAttempt => TimeSpan.FromSeconds(2), // Calculated retry delay
(exception, timeSpan, retryCount, context) =>
{
Console.WriteLine("Retry " + retryCount + " due to " + exception.Message);
});
// Execute the retry policy asynchronously
var pdf = await retryPolicy.ExecuteAsync(async () =>
{
var data = await FetchDataFromExternalApiAsync(); // Fetch data from an external source
return GeneratePdfFromData(data); // Generate PDF using fetched data
});
pdf.SaveAs("GeneratedDocument.pdf");
}
// Simulate fetching data from an external API
static async Task<string> FetchDataFromExternalApiAsync()
{
await Task.Delay(100); // Simulate delay
throw new HttpRequestException("Failed to fetch data from external API");
}
// Generate PDF using IronPDF based on the fetched data
static PdfDocument GeneratePdfFromData(string data)
{
var htmlContent = "<html><body><h1>Data: " + data + "</h1></body></html>";
var renderer = new ChromePdfRenderer();
return renderer.RenderHtmlAsPdf(htmlContent);
}
}
}
using System;
using System.Net.Http;
using System.Threading.Tasks;
using IronPdf;
using Polly;
namespace IronPdfWithPollyRetry
{
public class Program
{
public static async Task Main(string[] args)
{
// Define a retry policy with async capability
var retryPolicy = Policy
.Handle<HttpRequestException>() // Specify exception type to handle
.WaitAndRetryAsync(
3, // Retry attempts
retryAttempt => TimeSpan.FromSeconds(2), // Calculated retry delay
(exception, timeSpan, retryCount, context) =>
{
Console.WriteLine("Retry " + retryCount + " due to " + exception.Message);
});
// Execute the retry policy asynchronously
var pdf = await retryPolicy.ExecuteAsync(async () =>
{
var data = await FetchDataFromExternalApiAsync(); // Fetch data from an external source
return GeneratePdfFromData(data); // Generate PDF using fetched data
});
pdf.SaveAs("GeneratedDocument.pdf");
}
// Simulate fetching data from an external API
static async Task<string> FetchDataFromExternalApiAsync()
{
await Task.Delay(100); // Simulate delay
throw new HttpRequestException("Failed to fetch data from external API");
}
// Generate PDF using IronPDF based on the fetched data
static PdfDocument GeneratePdfFromData(string data)
{
var htmlContent = "<html><body><h1>Data: " + data + "</h1></body></html>";
var renderer = new ChromePdfRenderer();
return renderer.RenderHtmlAsPdf(htmlContent);
}
}
}
Imports System
Imports System.Net.Http
Imports System.Threading.Tasks
Imports IronPdf
Imports Polly
Namespace IronPdfWithPollyRetry
Public Class Program
Public Shared Async Function Main(ByVal args() As String) As Task
' Define a retry policy with async capability
Dim retryPolicy = Policy.Handle(Of HttpRequestException)().WaitAndRetryAsync(3, Function(retryAttempt) TimeSpan.FromSeconds(2), Sub(exception, timeSpan, retryCount, context)
Console.WriteLine("Retry " & retryCount & " due to " & exception.Message)
End Sub)
' Execute the retry policy asynchronously
Dim pdf = Await retryPolicy.ExecuteAsync(Async Function()
Dim data = Await FetchDataFromExternalApiAsync() ' Fetch data from an external source
Return GeneratePdfFromData(data) ' Generate PDF using fetched data
End Function)
pdf.SaveAs("GeneratedDocument.pdf")
End Function
' Simulate fetching data from an external API
Private Shared Async Function FetchDataFromExternalApiAsync() As Task(Of String)
Await Task.Delay(100) ' Simulate delay
Throw New HttpRequestException("Failed to fetch data from external API")
End Function
' Generate PDF using IronPDF based on the fetched data
Private Shared Function GeneratePdfFromData(ByVal data As String) As PdfDocument
Dim htmlContent = "<html><body><h1>Data: " & data & "</h1></body></html>"
Dim renderer = New ChromePdfRenderer()
Return renderer.RenderHtmlAsPdf(htmlContent)
End Function
End Class
End Namespace
此 C# 程式碼示範如何使用 Polly 函式庫與 IronPDF 實作重試政策,以產生 PDF 文件。 Main 方法使用 Polly 的 WaitAndRetryAsync 方法初始化重試策略。
該策略規定,應處理 HttpRequestException,並重試操作最多 3 次,首次嘗試和重試之間間隔 2 秒。 如果重試失敗,則會將訊息列印到控制台,指出重試嘗試的次數和異常訊息。
在 Main 方法內部,重試策略邏輯使用 retryPolicy.ExecuteAsync() 非同步執行。 在此執行過程中,兩個非同步操作連結在一起:FetchDataFromExternalApiAsync() 和 GeneratePdfFromData(data)。
如果 FetchDataFromExternalApiAsync() 失敗(這是故意設定的,模擬異常),重試策略將捕獲 HttpRequestException,記錄重試嘗試,並重試操作。
FetchDataFromExternalApiAsync() 方法模擬從外部 API 獲取資料並延遲,並故意拋出 HttpRequestException 以模擬請求失敗。

結論
總而言之,Polly 的重試原則對於處理 C# 應用程式中的暫態故障並確保穩健性而言,證明是無價之寶。 其在設定重試嘗試、延遲和條件方面的靈活性,可讓開發人員根據特定需求量身打造彈性策略。
無論是獨立使用或與 IronPDF 等函式庫搭配使用,Polly 都能協助建立可從暫時故障中優雅恢復的應用程式,提升使用者體驗與軟體的可靠性。
透過整合 Polly 的重試功能,開發人員可以建立更具彈性的系統,能夠適應並從瞬間問題中恢復,最終提升應用程式的整體品質與可靠性。
IronPDF 是市場上最好的 C# PDF 庫,它還提供IronPDF 的試用許可證,價格從 $799 美元起。
要瞭解如何使用 IronPDF 將 HTML 轉換為 PDF,請造訪以下 IronPDF HTML 至 PDF 轉換教學。
常見問題解答
什麼是C#中的Polly重試?
Polly重試是C#中Polly庫的一個功能,允許開發人員自動重試由於暫時問題如網路故障或服務不可用導致失敗的操作。這有助於通過優雅處理瞬態故障來構建具韌性的應用程式。
如何使用Polly實現基本的重試策略?
可以在Polly中通過處理如HttpRequestException等異常來實現基本重試策略,並將其設置為最多重試三次,每次嘗試之間固定延遲兩秒。
Polly中的指數退避有什麼意義?
Polly中的指數退避用於指數增加重試間的延遲,這有助於在故障期間減少服務的負載。這可以使用Polly的WaitAndRetry方法來實現,該方法基於指數增長計算延遲。
如何在C#項目中安裝Polly?
可以通過NuGet包管理器控制台使用命令Install-Package Polly或通過.NET CLI使用dotnet add package Polly在C#項目中安裝Polly。
Polly的重試策略可以與其他韌性策略結合嗎?
是的,Polly允許您將其重試策略與其他韌性策略(如斷路器)結合使用,通過Policy.Wrap方法增強應用程式的韌性,並防止服務持續失敗時重複重試。
怎樣在 C# 中將 HTML 轉換為 PDF?
可以使用IronPDF的方法如RenderHtmlAsPdf將HTML字串轉換為PDF。IronPDF還支援將HTML文件和網頁(包括CSS)轉換為PDF格式。
為什麼Polly的重試策略對於C#應用程式很重要?
Polly的重試策略對於處理C#應用程式中的瞬態故障至關重要,這確保了健壯性並通過允許系統從暫時故障中恢復而不崩潰來改善用戶體驗。
如何在PDF生成過程中實現重試策略?
在生成PDF時,可以使用Polly來實現重試策略以處理瞬態故障。通過將Polly的重試能力與IronPDF整合,可以在臨時網路或服務問題的情況下多次嘗試PDF操作。
如何安裝像IronPDF這樣的C# PDF庫?
IronPDF可以通過NuGet包管理器使用命令Install-Package IronPDF安裝,允許在您的C#應用程式中創建、編輯和操控PDF文件。
使用IronPDF生成PDF的好處是什麼?
IronPDF為在.NET應用程式中創建和操控PDF文件提供了強大的功能。它支援將HTML、CSS和網頁轉換為PDF,添加文字和圖像,並使用加密保護文件。



