可复原应用开发简介

复原能力是应用能够从暂时性故障中恢复并继续正常运行。 在 .NET 编程的上下文中,通过设计可正常处理故障并快速恢复的应用来实现复原能力。 为了帮助在 .NET 中构建可复原的应用,NuGet 上提供了以下两个包:

NuGet 包 DESCRIPTION
📦 Microsoft.Extensions.Resilience 此 NuGet 包提供机制来强化应用免受暂时性故障的影响。
📦 Microsoft.Extensions.Http.Resilience 此 NuGet 包专门为 HttpClient 类提供复原机制。

这两个 NuGet 包基于 Polly 构建,这是一个常用的开源项目。 Polly 是一个 .NET 复原和暂时性故障处理库,可让开发人员以流畅且线程安全的方式表达 重试断路器、超时、 大容量隔离速率限制、回退和对冲等策略。

重要

Microsoft.Extensions.Http.Polly NuGet 包已弃用。 请改用上述任一软件包。

开始吧

若要在 .NET 中开始使用复原,请安装 Microsoft.Extensions.Resilience NuGet 包。

dotnet add package Microsoft.Extensions.Resilience

有关详细信息,请参阅 dotnet add package 添加管理 .NET 应用程序中的包依赖项

构建韧性管道

若要使用复原能力,必须先构建基于复原策略的管道。 每个配置的策略按配置顺序执行。 换句话说,顺序很重要。 入口点是类型 IServiceCollection 上的扩展方法,名为 AddResiliencePipeline. 此方法接收管道的标识符和配置管道的委托。 委托会传递一个 ResiliencePipelineBuilder 实例,用于将复原能力策略添加到管道中。

请考虑以下基于 key 字符串的示例:

using Microsoft.Extensions.DependencyInjection;
using Polly;
using Polly.CircuitBreaker;
using Polly.Registry;
using Polly.Retry;
using Polly.Timeout;

var services = new ServiceCollection();

const string key = "Retry-Timeout";

services.AddResiliencePipeline(key, static builder =>
{
    // See: https://www.pollydocs.org/strategies/retry.html
    builder.AddRetry(new RetryStrategyOptions
    {
        ShouldHandle = new PredicateBuilder().Handle<TimeoutRejectedException>()
    });

    // See: https://www.pollydocs.org/strategies/timeout.html
    builder.AddTimeout(TimeSpan.FromSeconds(1.5));
});

前面的代码:

  • 创建新的 ServiceCollection 实例。
  • 定义一个key以标识管道。
  • 将复原管道添加到 ServiceCollection 实例。
  • 使用重试和超时策略配置管道。

每个管道都是为给定的 key 配置的,每个 key 用于从提供程序获取管道时识别其对应的 ResiliencePipelinekey这是方法的AddResiliencePipeline泛型类型参数。

复原能力管道构建器扩展

若要向管道添加策略,请在实例上Add*调用任何可用的ResiliencePipelineBuilder扩展方法。

  • AddRetry:发生故障时请尝试重试,这在问题是暂时性的并可能会自行消失时非常有用。
  • AddCircuitBreaker:如果某事出故障或繁忙,请停止尝试,这样可以避免浪费时间,并避免使事情变得更糟。
  • AddTimeout:如果某个事情花费的时间过长,就放弃,这样可以释放资源,提高性能。
  • AddRateLimiter:限制接受的请求数,从而控制入站负载。
  • AddConcurrencyLimiter:限制发出的请求数,使你能够控制出站负载。
  • AddFallback:在遇到故障时采取其他行动,从而提高用户体验。
  • AddHedging:在出现高延迟或故障时发出多个请求,这可以提高响应能力。

有关详细信息,请参阅 复原策略。 有关示例,请参阅 生成可复原 HTTP 应用:关键开发模式

指标扩充

扩充是以名称/值对的形式,自动增强遥测数据的已知状态。 例如,应用程序可能会发出一个日志,其中包含 操作结果代码 作为列,以表示某些操作的结果。 在这种情况下,扩充将 群集名称进程名称区域租户 ID 等添加到发送到遥测后端的日志中,具体取决于外围上下文。 添加扩充后,应用代码无需执行任何额外作即可从扩充指标中获益。

扩充的工作原理

假设有 1,000 个全局分布式服务实例生成日志和指标。 在 服务仪表板上遇到问题时,快速识别有问题的区域或数据中心至关重要。 扩充可确保指标记录包含必要的信息来查明分布式系统中的故障。 如果没有扩充,应用代码将承担内部管理此状态、将其集成到日志记录过程中并手动传输的负担。 扩充简化了此过程,无需影响应用的逻辑即可无缝处理它。

在弹性情况下,当添加扩充时,会在传出遥测数据中添加以下维度:

  • error.type:异常信息的低基数版本。
  • request.name:请求的名称。
  • request.dependency.name:依赖项的名称。

在 Polly 遥测 MeteringEnricher 的基础上进行了复原能力扩充。 有关更多信息,请参阅 Polly:计量扩充

添加复原能力扩充

除了注册复原能力管道之外,还可以注册复原能力扩充。 若要添加扩充,请在 AddResilienceEnricher(IServiceCollection) 实例上 IServiceCollection 调用扩展方法。

services.AddResilienceEnricher();

通过调用 AddResilienceEnricher 扩展方法,你将在内置于基础 Polly 库的默认维度之上添加维度。 添加了以下丰富维度:

使用弹性管道

要使用已配置的弹性管道,必须从 ResiliencePipelineProvider<TKey> 获取管道。 在您之前添加管道时,keystring 类型,因此必须从 ResiliencePipelineProvider<string> 获取管道。

using ServiceProvider provider = services.BuildServiceProvider();

ResiliencePipelineProvider<string> pipelineProvider =
    provider.GetRequiredService<ResiliencePipelineProvider<string>>();

ResiliencePipeline pipeline = pipelineProvider.GetPipeline(key);

前面的代码:

  • ServiceProvider实例生成一个ServiceCollection
  • 从服务提供程序获取 ResiliencePipelineProvider<string>
  • ResiliencePipeline 检索 ResiliencePipelineProvider<string>

执行复原能力管道

若要使用复原管道,请调用实例上Execute*的任何可用ResiliencePipeline方法。 例如,请考虑对ExecuteAsync方法进行一次示例调用。

await pipeline.ExecuteAsync(static cancellationToken =>
{
    // Code that could potentially fail.

    return ValueTask.CompletedTask;
});

前面的代码在 ExecuteAsync 方法中执行委托。 发生故障时,将执行配置的策略。 例如,如果 RetryStrategy 配置为重试三次,则会在传播失败结果之前执行委托共四次(一次初始尝试加上三次重试尝试)。

后续步骤