Skip to content

Commit

Permalink
[Docs] Update circuit-breaker docs for HTTP scenarios (#1831)
Browse files Browse the repository at this point in the history
  • Loading branch information
martintmk authored Nov 29, 2023
1 parent 3d5c47d commit 8203b45
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 24 deletions.
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsVersion)" />
Expand Down
44 changes: 21 additions & 23 deletions docs/strategies/circuit-breaker.md
Original file line number Diff line number Diff line change
Expand Up @@ -505,37 +505,35 @@ await uriToCbMappings[downstream1Uri].ExecuteAsync(CallXYZOnDownstream1, Cancell

✅ DO

Use named and typed `HttpClient`s:
Use named `HttpClient`s and then call `AddResilienceHandler` extension that is included in the [`Microsoft.Extensions.Http.Resilience`](https://www.nuget.org/packages/Microsoft.Extensions.Http.Resilience) package.

<!-- snippet: circuit-breaker-pattern-cb-per-endpoint -->
```cs
foreach (string uri in uris)
{
builder.Services
.AddHttpClient<IResilientClient, ResilientClient>(uri, client => client.BaseAddress = new Uri(uri))
.AddPolicyHandler(GetCircuitBreaker().AsAsyncPolicy<HttpResponseMessage>());
}
services
.AddHttpClient("my-client")
.AddResilienceHandler("circuit-breaker", builder =>
{
builder.AddCircuitBreaker(new());
})
.SelectPipelineByAuthority(); // This call ensures that circuit breaker is cached by each URL authority
```
<!-- endSnippet -->

...
private const string serviceUrl = "https://downstream1.com";
public Downstream1Client(
IHttpClientFactory namedClientFactory,
ITypedHttpClientFactory<ResilientClient> typedClientFactory)
{
var namedClient = namedClientFactory.CreateClient(serviceUrl);
var namedTypedClient = typedClientFactory.CreateClient(namedClient);
...
}
And then use it:

<!-- snippet: circuit-breaker-pattern-cb-per-endpoint-usage -->
```cs
HttpClient client = httpClientFactory.CreateClient("my-client");

await client.GetAsync(new Uri("https://downstream1.com/some-path"));
```
<!-- endSnippet -->

**Reasoning**:

- The `HttpClient` integrates with Circuit Breaker during startup.
- The `HttpClient` integrates with Circuit Breaker during startup by using the `AddResilienceHandler` extension.
- There's no need to call `ExecuteAsync()` directly. The `DelegatingHandler` handles it automatically.

> [!NOTE]
> The above sample code used the `AsAsyncPolicy<HttpResponseMessage>()` method to convert the `ResiliencePipeline<HttpResponseMessage>` to `IAsyncPolicy<HttpResponseMessage>`.
> It is required because the `AddPolicyHandler()` method anticipates an `IAsyncPolicy<HttpResponse>` parameter.
> Please be aware that, later an `AddResilienceHandler()` will be introduced in the `Microsoft.Extensions.Http.Resilience` package which is the successor of the `Microsoft.Extensions.Http.Polly`.
- By using the `SelectPipelineByAuthority` extension method, the resilience handler caches and assigns resilience pipeline to each authority (scheme + host + port) that is extracted from HTTP request message.

### Reducing thrown exceptions

Expand Down
32 changes: 31 additions & 1 deletion src/Snippets/Docs/CircuitBreaker.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using System.Net;
using System;
using System.Net;
using System.Net.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Http.Resilience;
using Polly.CircuitBreaker;
using Snippets.Docs.Utils;

Expand Down Expand Up @@ -215,6 +218,33 @@ [new Uri("https://downstreamN.com")] = GetCircuitBreaker()
#endregion
}

public static async ValueTask Pattern_CircuitPerEndpoint()
{
var services = new ServiceCollection();

#region circuit-breaker-pattern-cb-per-endpoint

services
.AddHttpClient("my-client")
.AddResilienceHandler("circuit-breaker", builder =>
{
builder.AddCircuitBreaker(new());
})
.SelectPipelineByAuthority(); // This call ensures that circuit breaker is cached by each URL authority

#endregion

IHttpClientFactory httpClientFactory = null!;

#region circuit-breaker-pattern-cb-per-endpoint-usage

HttpClient client = httpClientFactory.CreateClient("my-client");

await client.GetAsync(new Uri("https://downstream1.com/some-path"));

#endregion
}

private static ValueTask<HttpResponseMessage> IssueRequest() => ValueTask.FromResult(new HttpResponseMessage());
public static async ValueTask AntiPattern_ReduceThrownExceptions()
{
Expand Down
1 change: 1 addition & 0 deletions src/Snippets/Snippets.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Http.Resilience" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" />
<PackageReference Include="xunit" />
</ItemGroup>
Expand Down

0 comments on commit 8203b45

Please sign in to comment.