@mjovanovictech: 我们有两款官方的 NuGet 包,用于增强弹性:- Microsoft.Extensions.Resilience - Microsoft.Extensions.Http.Resil…
摘要
文章介绍了两款官方的 NuGet 包:Microsoft.Extensions.Resilience 和 Microsoft.Extensions.Http.Resilience,用于构建具有内置策略的弹性 .NET 应用程序,这些策略包括重试、超时和断路器。
查看缓存全文
缓存时间: 2026/08/16 09:59
我们有两个官方 NuGet 包用于实现弹性:
- Microsoft.Extensions.Resilience
- Microsoft.Extensions.Http.Resilience
它们基于 Polly 构建,因此 API 会很熟悉。你可以使用它们在 C# 中定义弹性策略。以下是一些开箱即用的策略:
- 重试
- 超时
- 备用方案
- 熔断器
以下是你如何使用它们来构建弹性 .NET 应用程序的方法:
https://milanjovanovic.tech/blog/building-resilient-cloud-applications-with-dotnet?utm_source=X&utm_medium=social&utm_campaign=10.08.2026
使用 .NET 构建弹性云应用程序
来源:https://milanjovanovic.tech/blog/building-resilient-cloud-applications-with-dotnet?utm_source=X&utm_medium=social&utm_campaign=10.08.2026
使用 Postman Flows (https://learning.postman.com/docs/postman-flows/gs/flows-overview/) 可视化构建 API 应用程序。Postman Flows 是一个用于在 API 优先世界中构建 API 驱动应用程序的可视化工具。你可以使用 Flows 在 Postman 工作区中链接请求、处理数据并创建真实的工作流。从这里开始 (https://learning.postman.com/docs/postman-flows/gs/flows-overview/)。
构建 Blazor Web 应用程序的 9 个最佳实践 (https://www.telerik.com/blogs/blazor-basics-9-best-practices-building-blazor-web-applications?utm_medium=cpm&utm_source=milanjovanovic&utm_campaign=blazor-general-awareness):在本文中,你将学习由 .NET 开发者和 YouTube 影响者 Claudio Bernasconi 总结的构建 Blazor Web 应用程序的九个最佳实践。在这里阅读 (https://www.telerik.com/blogs/blazor-basics-9-best-practices-building-blazor-web-applications?utm_medium=cpm&utm_source=milanjovanovic&utm_campaign=blazor-general-awareness)。
根据我处理微服务系统的经验,事情并非总是按计划进行。网络请求会随机失败,应用程序服务器可能过载,并出现意外错误。这就是弹性发挥作用的地方。弹性应用程序能够从临时故障中恢复并继续运行。弹性是通过设计能够优雅处理故障并快速恢复的应用程序来实现的。通过将弹性思维融入应用程序设计,你可以创建健壮且可靠的系统,即使面临困难。在本期通讯中,我们将探讨 .NET 中用于构建弹性系统的工具和技术。
弹性:为何你应关注它 (https://milanjovanovic.tech/blog/building-resilient-cloud-applications-with-dotnet?utm_source=X&utm_medium=social&utm_campaign=10.08.2026#resilience-why-you-should-care)
发送 HTTP 请求是服务间远程通信的常见方式。然而,HTTP 请求容易因网络或服务器问题而出现故障。这些故障会破坏服务可用性,尤其是随着依赖项增加和级联故障风险增长。那么,如何提高应用程序和服务的弹性呢?以下是一些可考虑的提升弹性的策略:
- 重试:重试因临时错误而失败的请求。
- 超时:取消超过指定时间限制的请求。
- 备用方案:为失败的操作定义替代动作或结果。
- 熔断器:暂时中断与不可用服务的通信。
你可以单独或组合使用这些策略,以获得最佳的 HTTP 请求弹性。让我们看看如何在 .NET 应用程序中引入弹性。
弹性管道 (https://milanjovanovic.tech/blog/building-resilient-cloud-applications-with-dotnet?utm_source=X&utm_medium=social&utm_campaign=10.08.2026#resilience-pipelines)
在 .NET 8 中,将弹性集成到应用程序中变得更加简单。我们可以使用 Microsoft.Extensions.Resilience 和 Microsoft.Extensions.Http.Resilience,它们建立在 Polly 之上。Polly 是一个 .NET 弹性和临时故障处理库。Polly 允许我们定义弹性策略,如重试、熔断器、超时、速率限制、备用方案和对冲。Polly 在其最新版本 (V8) 中引入了新的 API 表面,该版本是与微软合作实现的。你可以通过 此视频了解更多关于 Polly V8 API 的信息 (https://youtu.be/PqVQFUCTzUM)。
如果你之前使用 Microsoft.Extensions.Http.Polly,建议切换到前面提到的包之一。让我们从安装所需的 NuGet 包开始:
Install-Package Microsoft.Extensions.Resilience
Install-Package Microsoft.Extensions.Http.Resilience
要使用弹性,你必须首先构建一个由弹性策略组成的管道。我们配置为管道一部分的每个策略都将按配置顺序执行。顺序在弹性管道中非常重要。请记住这一点。
我们从创建 ResiliencePipelineBuilder 实例开始,它允许我们配置弹性策略。
ResiliencePipeline pipeline = new ResiliencePipelineBuilder()
.AddRetry(new RetryStrategyOptions
{
ShouldHandle = new PredicateBuilder().Handle<HttpRequestException>(),
Delay = TimeSpan.FromSeconds(1),
MaxRetryAttempts = 2,
BackoffType = DelayBackoffType.Exponential,
UseJitter = true
})
.AddTimeout(new TimeoutStrategyOptions
{
Timeout = TimeSpan.FromSeconds(10)
})
.Build();
await pipeline.ExecuteAsync(
async ct => await httpClient.GetAsync("https://modularmonolith.com", ct),
cancellationToken);
以下是我们添加到弹性管道的内容:
AddRetry- 配置重试弹性策略,我们可以通过传入RetryStrategyOptions实例来进一步配置它。我们可以为ShouldHandle属性提供一个谓词,以定义弹性策略应处理哪些异常。重试策略还带有一些合理的默认值。AddTimeout- 配置超时策略,如果委托在超时前未完成,将抛出TimeoutRejectedException。我们可以通过传入TimeoutStrategyOptions实例来提供自定义超时。默认超时为 30 秒。
最后,我们可以 Build 弹性管道并获得一个已配置的 ResiliencePipeline 实例,该实例将应用相应的弹性策略。要使用 ResiliencePipeline,我们可以调用 ExecuteAsync 方法并传入一个委托。
弹性管道与依赖注入 (https://milanjovanovic.tech/blog/building-resilient-cloud-applications-with-dotnet?utm_source=X&utm_medium=social&utm_campaign=10.08.2026#resilience-pipelines-and-dependency-injection)
每次使用时都配置弹性管道是很繁琐的。.NET 8 为 IServiceCollection 接口引入了一个新的扩展方法,允许我们将弹性管道注册到依赖注入中。你不再需要每次手动配置弹性,而是按名称请求一个预构建的管道。
我们首先调用 AddResiliencePipeline 方法,它允许我们配置弹性管道。每个弹性管道都需要一个唯一的键。我们可以使用此键来解析相应的弹性管道实例。在此示例中,我们传入一个 string 键,它允许我们配置非泛型的 ResiliencePipelineBuilder。
services.AddResiliencePipeline("retry", builder =>
{
builder.AddRetry(new RetryStrategyOptions
{
Delay = TimeSpan.FromSeconds(1),
MaxRetryAttempts = 2,
BackoffType = DelayBackoffType.Exponential,
UseJitter = true
});
});
然而,在调用 AddResiliencePipeline 时,我们也可以指定泛型参数。这允许我们使用 ResiliencePipelineBuilder 配置类型化的弹性管道。使用这种方法,我们可以访问 对冲 和 备用方案 策略。在以下示例中,我们通过调用 AddFallback 配置备用方案策略。这允许我们提供一个备用值,在故障时返回。备用方案可以是静态值,也可以来自另一个 HTTP 请求或数据库。
services.AddResiliencePipeline("gh-fallback", builder =>
{
builder.AddFallback(new FallbackStrategyOptions
{
FallbackAction = _ => Outcome.FromResultAsValueTask(GitHubUser.Empty)
});
});
要使用通过依赖注入配置的弹性管道,我们可以使用 ResiliencePipelineProvider。它公开了一个 GetPipeline 方法来获取管道实例。我们必须提供用于注册弹性管道的键。
app.MapGet("users", async (
HttpClient httpClient,
ResiliencePipelineProvider pipelineProvider) =>
{
ResiliencePipeline pipeline = pipelineProvider.GetPipeline("gh-fallback");
var user = await pipeline.ExecuteAsync(
async token => await httpClient.GetAsync("api/users", token),
cancellationToken);
});
弹性策略与 Polly (https://milanjovanovic.tech/blog/building-resilient-cloud-applications-with-dotnet?utm_source=X&utm_medium=social&utm_campaign=10.08.2026#resilience-strategies-and-polly)
弹性策略 是 Polly 的核心组件。它们旨在运行自定义回调,同时引入额外的弹性层。我们不能直接运行这些策略。相反,我们通过弹性管道执行它们。
Polly 将弹性策略分为响应式和主动式。响应式策略处理特定的异常或结果。主动式策略决定使用速率限制器或超时弹性策略来取消或拒绝回调的执行。
Polly 具有以下内置弹性策略:
- 重试:经典的“再试一次”方法。适用于临时的网络抖动。你可以配置重试次数,甚至可以添加一些随机性(抖动),以避免所有人同时重试导致系统过载。
- 熔断器:像电路断路器一样,这可以防止对失败的系统发起猛攻。如果错误堆积,熔断器会暂时“跳闸”,让系统有时间恢复。
- 备用方案:如果主调用失败,提供一个安全的默认响应。它可能是一个缓存的结果或一条简单的“服务不可用”消息。
- 对冲:同时发起多个请求,接受第一个成功的响应。如果你的系统有多种方式处理某事,这会很有用。
- 超时:如果请求超时则终止,防止请求无限期挂起。
- 速率限制器:节制传出请求,防止压垮外部服务。
HTTP 请求弹性 (https://milanjovanovic.tech/blog/building-resilient-cloud-applications-with-dotnet?utm_source=X&utm_medium=social&utm_campaign=10.08.2026#http-request-resilience)
向外部服务发送 HTTP 调用是你的应用程序与外界交互的方式。这些可以是第三方服务,如支付网关和身份提供商,也可以是你团队拥有和运营的其他服务。
Microsoft.Extensions.Http.Resilience 库提供了开箱即用的弹性管道,用于发送 HTTP 请求。我们可以使用 AddStandardResilienceHandler 方法为传出的 HttpClient 请求 添加弹性。
services.AddHttpClient(static (httpClient) =>
{
httpClient.BaseAddress = new Uri("https://api.github.com/");
})
.AddStandardResilienceHandler();
这也意味着你可以消除之前用于弹性的任何委托处理程序。标准弹性处理程序结合了五种 Polly 策略,创建了一个适用于大多数场景的弹性管道。标准管道包含以下策略:
- 速率限制器:限制发送到依赖项的并发请求数。
- 总请求超时:引入一个总超时,包括任何重试尝试。
- 重试:如果请求因超时或临时错误而失败,则重试该请求。
- 熔断器:如果检测到过多故障,则阻止发送更多请求。
- 尝试超时:为单个请求引入超时。
你可以通过配置 HttpStandardResilienceOptions 来自定义标准弹性管道的任何方面。
总结 (https://milanjovanovic.tech/blog/building-resilient-cloud-applications-with-dotnet?utm_source=X&utm_medium=social&utm_campaign=10.08.2026#takeaway)
弹性不仅仅是一个流行词;它是构建可靠软件系统的核心原则。我们很幸运能拥有像 Microsoft.Extensions.Resilience 和 Polly 这样的强大工具。我们可以使用它们来设计能够优雅处理任何临时故障的系统。
良好的监控和可观测性对于理解你的弹性机制在生产环境中的工作方式至关重要。请记住,目标不是消除故障,而是优雅地处理故障并保持应用程序正常运行。
准备好深入了解弹性架构了吗?我的关于构建模块化单体 的进阶课程将使你掌握设计和实现健壮、可扩展系统的技能。查看 模块化单体架构 (https://milanjovanovic.tech/modular-monolith-architecture)。
挑战:看看你现有的 .NET 项目。是否有任何关键领域,其中一点弹性就能带来很大帮助?选择一个,并尝试应用我们在此讨论的一些技巧。
今天就到这里。下周见。
相似文章
ResilixForge — Python异步弹性工具包:重试、断路器、舱壁、速率限制 [Apache-2.0]
ResilixForge 是一个采用 Apache-2.0 许可的 Python 异步弹性工具包,提供重试、断路器、舱壁和速率限制器。
我们狠狠撞上了重试问题,干脆开源了一个解决方案
Replaysafe 是一个开源的 npm 库,通过对操作进行指纹识别来确保幂等重试,防止 AI 智能体工作流中出现重复的副作用。它集成了 LangGraph、CrewAI 等流行框架。
dotnet/skills
.NET 团队为编码代理精心策划的核心技能与自定义代理集合,涵盖 .NET 编码、数据访问、诊断、MSBuild、NuGet、升级、MAUI、AI、模板、测试、ASP.NET 以及 .NET 11。
微软发布AI安全工具,称其性能优于竞争平台
微软宣布推出两款新的AI驱动安全工具MDASH和Project Perception,声称它们在CyberGYM等基准测试中性能优于竞争平台,并通过为每项任务选择最佳模型来降低成本。
@Akintola_steve: https://x.com/Akintola_steve/status/2055620856802357587
一份实用的蓝图,用于设计能够处理100万并发用户的后端系统,涵盖架构决策如语言选择、负载均衡、数据库分片、多层缓存及弹性模式。