|  | 
|  | 1 | +--- | 
|  | 2 | +title: Introduction to resilient app development | 
|  | 3 | +description: Learn about resiliency as it relates to .NET and how to build a resilience pipeline. | 
|  | 4 | +author: IEvangelist | 
|  | 5 | +ms.author: dapine | 
|  | 6 | +ms.date: 10/20/2023 | 
|  | 7 | +--- | 
|  | 8 | + | 
|  | 9 | +# Introduction to resilient app development | 
|  | 10 | + | 
|  | 11 | +Resiliency is the ability of an app to recover from failures and continue to function. In the context of .NET programming, resilience is achieved by designing apps that can handle failures gracefully and recover quickly. To help build resilient apps in .NET, the following two packages are available on NuGet: | 
|  | 12 | + | 
|  | 13 | +| NuGet package | Description | | 
|  | 14 | +|--|--| | 
|  | 15 | +| [📦 Microsoft.Extensions.Resilience](https://www.nuget.org/packages/Microsoft.Extensions.Resilience) | This NuGet package provides mechanisms to harden apps against transient failures. | | 
|  | 16 | +| [📦 Microsoft.Extensions.Http.Resilience](https://www.nuget.org/packages/Microsoft.Extensions.Http.Resilience) | This NuGet package provides resilience mechanisms specifically for the <xref:System.Net.Http.HttpClient> class. | | 
|  | 17 | + | 
|  | 18 | +These two NuGet packages are built on top of [Polly](https://github.com/App-vNext/Polly), which is a popular open-source project. Polly is a .NET resilience and transient fault-handling library that allows developers to express strategies such as retry, circuit breaker, timeout, bulkhead isolation, rate-limiting, fallback, and hedging in a fluent and thread-safe manner. | 
|  | 19 | + | 
|  | 20 | +> [!IMPORTANT] | 
|  | 21 | +> The [Microsoft.Extensions.Http.Polly](https://www.nuget.org/packages/Microsoft.Extensions.Http.Polly) NuGet package is deprecated. Use either of the aforementioned packages instead. | 
|  | 22 | +
 | 
|  | 23 | +## Get started | 
|  | 24 | + | 
|  | 25 | +To get started with resilience in .NET, install the [Microsoft.Extensions.Resilience](https://www.nuget.org/packages/Microsoft.Extensions.Resilience) NuGet package. | 
|  | 26 | + | 
|  | 27 | +### [.NET CLI](#tab/dotnet-cli) | 
|  | 28 | + | 
|  | 29 | +```dotnetcli | 
|  | 30 | +dotnet add package Microsoft.Extensions.Resilience --version 8.0.0 | 
|  | 31 | +``` | 
|  | 32 | + | 
|  | 33 | +### [PackageReference](#tab/package-reference) | 
|  | 34 | + | 
|  | 35 | +```xml | 
|  | 36 | +<PackageReference Include="Microsoft.Extensions.Resilience" Version="8.0.0" /> | 
|  | 37 | +``` | 
|  | 38 | + | 
|  | 39 | +--- | 
|  | 40 | + | 
|  | 41 | +For more information, see [dotnet add package](../tools/dotnet-add-package.md) or [Manage package dependencies in .NET applications](../tools/dependencies.md). | 
|  | 42 | + | 
|  | 43 | +## Build a resilience pipeline | 
|  | 44 | + | 
|  | 45 | +To use resilience, you must first build a pipeline of resilience-based strategies. Each configured strategy executes in order of configuration. In other words, order is important. The entry point is an extension method on the <xref:Microsoft.Extensions.DependencyInjection.IServiceCollection> type, named `AddResiliencePipeline`. This method takes an identifier of the pipeline and delegate that configures the pipeline. The delegate is passed an instance of `ResiliencePipelineBuilder`, which is used to add resilience strategies to the pipeline. | 
|  | 46 | + | 
|  | 47 | +Consider the following string-based `key` example: | 
|  | 48 | + | 
|  | 49 | +:::code language="csharp" source="snippets/resilience/Program.cs" id="setup"::: | 
|  | 50 | + | 
|  | 51 | +The preceding code: | 
|  | 52 | + | 
|  | 53 | +- Creates a new `ServiceCollection` instance. | 
|  | 54 | +- Defines a `key` to identify the pipeline. | 
|  | 55 | +- Adds a resilience pipeline to the `ServiceCollection` instance. | 
|  | 56 | +- Configures the pipeline with a retry strategy, circuit breaker strategy, and timeout strategy. | 
|  | 57 | + | 
|  | 58 | +Each pipeline is configured for a given `key`, and each `key` is used to identify its corresponding `ResiliencePipeline` when getting the pipeline from the provider. The `key` is a generic type parameter of the `AddResiliencePipeline` method. | 
|  | 59 | + | 
|  | 60 | +### Resilience pipeline builder extensions | 
|  | 61 | + | 
|  | 62 | +To add a strategy to the pipeline, call any of the available `Add*` extension methods on the `ResiliencePipelineBuilder` instance. | 
|  | 63 | + | 
|  | 64 | +- `AddRetry`: Try again if something fails, which is useful when the problem is temporary and might go away. | 
|  | 65 | +- `AddCircuitBreaker`: Stop trying if something is broken or busy, which benefits you by avoiding wasted time and making things worse. | 
|  | 66 | +- `AddTimeout`: Give up if something takes too long, which can improve performance by freeing up resources. | 
|  | 67 | +- `AddRateLimiter`: Limit how many requests you make or accept, which enables you to control load. | 
|  | 68 | +- `AddFallback`: Do something else when experiencing failures, which improves user experience. | 
|  | 69 | +- `AddHedging`: Do more than one thing at the same time and take the fastest one, which can improve responsiveness. | 
|  | 70 | + | 
|  | 71 | +For more information, see [Resilience strategies](https://www.pollydocs.org/strategies). | 
|  | 72 | + | 
|  | 73 | +## Add enrichment | 
|  | 74 | + | 
|  | 75 | +Enrichment is the automatic augmentation of telemetry with well-known state, in the form of name/value pairs. For example, an app might emit a log that includes the _operation_ and _result code_ as columns to represent the outcome of some operation. In this situation and depending on peripheral context, enrichment adds _Cluster name_, _Process name_, _Region_, _Tenant ID_, and more to the log as it's sent to the telemetry backend. When enrichment is added, the app code doesn't need to do anything extra to benefit from enriched metrics. | 
|  | 76 | + | 
|  | 77 | +Imagine 1,000 globally distributed service instances generating logs and metrics. When you encounter an issue on your service dashboard, it's crucial to quickly identify the problematic region or data center. Enrichment ensures that metric records contain the necessary information to pinpoint failures in distributed systems. Without enrichment, the burden falls on the app code to internally manage this state, integrate it into the logging process, and manually transmit it. Enrichment simplifies this process, seamlessly handling it without affecting the app's logic. | 
|  | 78 | + | 
|  | 79 | +### Add resilience enrichment | 
|  | 80 | + | 
|  | 81 | +In addition to registering a resilience pipeline, you can also register resilience enrichment. To add enrichment, call the `AddResilienceEnricher` extensions method on the `IServiceCollection` instance. | 
|  | 82 | + | 
|  | 83 | +:::code language="csharp" source="snippets/resilience/Program.cs" id="enricher"::: | 
|  | 84 | + | 
|  | 85 | +By calling the `AddResilienceEnricher` extension method, you're adding dimensions on top of the default ones that are built into the underlying Polly library. The following enrichment dimensions are added: | 
|  | 86 | + | 
|  | 87 | +- Exception enrichment based on the <xref:Microsoft.Extensions.Diagnostics.ExceptionSummarization.IExceptionSummarizer>, which provides a mechanism to summarize exceptions for use in telemetry. | 
|  | 88 | +- Result enrichment based on the <xref:Microsoft.Extensions.Resilience.FailureResultContext>, which captures the dimensions metered for transient fault failures. | 
|  | 89 | +- Request metadata enrichment based on <xref:Microsoft.Extensions.Http.Telemetry.RequestMetadata>, which holds the request metadata for telemetry. | 
|  | 90 | + | 
|  | 91 | +For more information, see [Polly: Telemetry metrics](https://www.pollydocs.org/advanced/telemetry#metrics). | 
|  | 92 | + | 
|  | 93 | +## Use resilience pipeline | 
|  | 94 | + | 
|  | 95 | +To use a configured resilience pipeline, you must get the pipeline from a `ResiliencePipelineProvider<TKey>`. When you added the pipeline earlier, the `key` was of type `string`, so you must get the pipeline from the `ResiliencePipelineProvider<string>`. | 
|  | 96 | + | 
|  | 97 | +:::code language="csharp" source="snippets/resilience/Program.cs" id="pipeline"::: | 
|  | 98 | + | 
|  | 99 | +The preceding code: | 
|  | 100 | + | 
|  | 101 | +- Builds a service provider from the `ServiceCollection` instance. | 
|  | 102 | +- Gets the `ResiliencePipelineProvider<string>` from the service provider. | 
|  | 103 | +- Retrieves the `ResiliencePipeline` from the `ResiliencePipelineProvider<string>`. | 
|  | 104 | + | 
|  | 105 | +## Execute resilience pipeline | 
|  | 106 | + | 
|  | 107 | +To use the resilience pipeline, call any of the available `Execute*` methods on the `ResiliencePipeline` instance. For example, consider an example call to `ExecuteAsync` method: | 
|  | 108 | + | 
|  | 109 | +:::code language="csharp" source="snippets/resilience/Program.cs" id="execute"::: | 
|  | 110 | + | 
|  | 111 | +The preceding code executes the delegate within the `ExecuteAsync` method. When there are failures, the configured strategies are executed. For example, if the `RetryStrategy` is configured to retry three times, the delegate is executed three times before the failure is propagated. | 
|  | 112 | + | 
|  | 113 | +## Next steps | 
|  | 114 | + | 
|  | 115 | +> [!div class="nextstepaction"] | 
|  | 116 | +> [Build resilient HTTP apps: Key development patterns](http-resilience.md) | 
0 commit comments