What is Hedging strategy in Polly v8 and how to implement it in .NET?

Asked 1 month ago Updated 1 month ago 141 views

1

Hedging executes additional concurrent attempts of an operation before the primary attempt finishes if it takes longer than expected. This decreases tail latency in high-availability systems.

Implementing Hedging with Polly

Hedging is ideal for idempotent operations (such as HTTP GET queries) where receiving the fastest successful response is critical.

Code Example

var pipeline = new ResiliencePipelineBuilder<HttpResponseMessage>()
    .AddHedging(new HedgingStrategyOptions<HttpResponseMessage>
    {
        MaxHedgedAttempts = 3,
        Delay = TimeSpan.FromMilliseconds(200),
        ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
            .Handle<HttpRequestException>()
            .HandleResult(res => !res.IsSuccessStatusCode)
    })
    .Build();

var response = await pipeline.ExecuteAsync(async ct =>
{
    return await httpClient.GetAsync("https://api.example.com/data", ct);
});

1 Answer


1

The Hedging strategy in Polly v8 is a proactive resilience mechanism designed to reduce tail latency in distributed systems. Instead of waiting for a slow request to time out or fail before trying again, Hedging automatically spawns additional concurrent attempts (hedged requests) if the primary request exceeds a specified delay threshold.

How Hedging Works

In high-throughput microservices, latency spikes (tail latency) can significantly impact user experience. Hedging addresses this issue through the following flow:

  • Primary Request: The original request is dispatched first.
  • Hedging Delay: If the primary request does not respond within a configured timeframe, a parallel request is triggered.
  • First Successful Response Wins: The result of the fastest successful attempt is returned immediately to the caller, and any remaining in-flight requests are cancelled.

Implementing Hedging in .NET using Polly v8

Polly v8 introduced the ResiliencePipelineBuilder<T> API, making it easy to construct typed resilience pipelines. Below is an example demonstrating how to configure and execute a Hedging strategy for an HTTP call in C#:

using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Polly;
using Polly.Hedging;

public class PollyHedgingDemo
{
    public static async Task RunAsync()
    {
        ResiliencePipeline<HttpResponseMessage> pipeline = new ResiliencePipelineBuilder<HttpResponseMessage>()
            .AddHedging(new HedgingStrategyOptions<HttpResponseMessage>
            {
                MaxHedgedAttempts = 3,
                Delay = TimeSpan.FromMilliseconds(300),
                ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
                    .HandleResult(response => !response.IsSuccessStatusCode)
                    .Handle<HttpRequestException>()
            })
            .Build();

        using var httpClient = new HttpClient();

        HttpResponseMessage response = await pipeline.ExecuteAsync(
            async cancellationToken =>
            {
                return await httpClient.GetAsync("https://api.example.com/data", cancellationToken);
            },
            CancellationToken.None);

        Console.WriteLine($"Response Status Code: {response.StatusCode}");
    }
}

Key Configuration Parameters

  • MaxHedgedAttempts: Specifies the maximum total attempts allowed, including the primary attempt and subsequent hedged calls.
  • Delay: Configures the duration to wait before starting the next hedged attempt while the previous attempt is still pending.
  • ShouldHandle: Defines which exception types or HTTP response status codes indicate a failure that warrants a hedged request.

Write Your Answer