HttpClientFacotry Part 4: 集成 Polly 处理瞬时失效

原文地址:https://www.stevejgordon.co.uk/httpclientfactory-using-polly-for-transient-fault-handling

在使用 Polly 之前,我们需要添加包引用到项目中,Microsoft.Extensions.Http.Polly 包。

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.1.0" />
</ItemGroup> </Project>

应用策略

Microsoft.Extensions.Http.Polly 包包含一个 IHttpClientBuilder 的扩展方法称为 AddPolicyHander() ,我们可以使用它增加处理器到 Polly 策略中。IHttpClientBuilder 在定名命名的客户端的时候被返回。

可以在 ConfigureServices() 方法中使用该扩展。

services.AddHttpClient("github")
.AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(10)));

在本示例中,我们定义了一个名为 github 的客户端,然后使用 AddPolicyHandler() 方法提供了超时策略。这里提供的策略必须是 IAsyncPolicy<HttpResponseMessage> 类型。该策略对于每个请求在 10s 之后超时。

重用策略

在使用 Polly 的时候,最佳实践是定义策略一次,然后在各种场景下共享该策略。通过这种方式,改变策略中的规则,只需要在一个地方进行修改。另外,它确保策略仅仅被分配一次。特别是,诸如短路策略,如果多个调用者期望同样的短路实例就需要共享。

对此种情况,我们定义超时策略一次,然后在两个命名客户端之间共享。

var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(10));

services.AddHttpClient("github")
.AddPolicyHandler(timeoutPolicy); services.AddHttpClient("google")
.AddPolicyHandler(timeoutPolicy);

当我们探索使用 PolicyRegistry 的时候,我们还将看到另一种重用策略的方式。

瞬时失效处理

在处理 HTTP 请求的时候,常见的一个问题是处理瞬时失效。由于这是常见的需求,Microsoft.Extensions.Http.Polly 包提供了一个专用的扩展,我们可以用来快速设置处理瞬时失效的策略。

例如,当瞬时失效发生的时候,对命名的 HttpClient 添加对请求的重试,我们可以如下注册重试策略:

services.AddHttpClient("github")
.AddTransientHttpErrorPolicy(p => p.RetryAsync(3));

在此示例中,所有通过该客户端发出的请求,当失效条件满足的时候将会被重试。AddTransientHttpErrorPolicy() 方法提供 Func<PolicyBuilder<HttpResponseMessage>, IAsyncPolicy<HttpResponseMessage>>。PolicyBuilder 将用来预配置处理 HttpRequestExceptions,任何返回 5xx 状态码和 408 状态码 (请求超时) 的响应。这适合多种状态,如果你需要策略应用到其它条件,你可以使用其它的重载提供更专用的策略。

但是注意,在执行重试的时候,需要考虑等幂问题,重试 GET 请求很安全,如果我们发出请求,然后没有收到任何响应,我们可以安全地没有任何危险地重试。但是,考虑一下我们重试一个 HTTP POST 请求,此时,我们必须更加小心,因为原来的请求可能已经被接收到,但是我们在接收响应的时候失败了。此时,重试会导致重复的数据,或者破坏在下游系统中存储的数据。此时,你需要更多的关于下游系统在收到相同的请求一次以上时如何处理的知识。重试还是安全的吗?当你拥有下游服务的时候,比较容易处理该问题,你可能,例如,使用某个唯一标识符来防止重复 POST。

当你无法控制下游系统,或者你知道重复的 POST 可能带来随后的负面影响,你将需要更加小心地控制策略。一个可能适合的方式是定义不同的命名/强类型的客户端,为有副作用的创建一个,为没有副作用的创建另外一个。然后,针对所采取的操作使用正确的客户端。然而,这可能变得有点难以管理。另一个更好的方式是使用 AddPolicyHandler 的重载。它使得我们可以访问 HttpRequestMessage,所以策略可以有条件地应用。该重载看起来如下所示:

AddPolicyHandler(Func<HttpRequestMessage, IAsyncPolicy<HttpResponseMessage>> policySelector)

我们将注意到 policySelector 委托可以访问 HttpRequestMessage,并且期待返回 IAsyncPolicy<HttpResponseMessage>。我们不需要访问 PolicyBuilder 的设置如前例所示来出来瞬时失败,如果我们希望处理通常的瞬时失效错误,我们需要为策略定义期望处理的条件。为了更加简便,Polly 项目包含了一个助手扩展,我们可以借助它设置好 PolicyBuilder 来处理通常的瞬时失效错误。为了使用该扩展方法,我们需要添加 Polly.Extensions.Http 包。

我们可以调用 HttpPolicyExtensions.HandleTranisentHttpError() 来获得一个 PolicyBuilder 对象,它被使用瞬时失效条件进行配置。我们可以使用 PolicyBuilder 来创建一个适当的重试策略,它可以在 Http Get 请求的时候,有条件地被应用,在该示例中,任何其它的请求方法将使用 NoOp 策略。

var retryPolicy = HttpPolicyExtensions
.HandleTransientHttpError()
.RetryAsync(3); var noOp = Policy.NoOpAsync().AsAsyncPolicy<HttpResponseMessage>(); services.AddHttpClient("github")
.AddPolicyHandler(request => request.Method == HttpMethod.Get ? retryPolicy : noOp);

使用策略注册表

最后一个示例,将演示如何通过一个策略注册表来应用策略。为了支持策略的重用,Polly 提供了 PolicyRegisty 的概念,它就是一个策略的容器。它可以在应用程序设置的时候添加策略到注册表中。该注册表然后可以各处使用,并通过名字来访问其中的策略。

在 IHttpClientBuilder 上的扩展方法也支持使用注册表为客户端基于处理器添加策略。

首先,我们必须在 DI 容器中添加一个 PolicyRegistry 的注册。Microsoft.Extensions.Http.Polly 包中包含了一些简化使用的扩展方法。在上面的示例中,我调用的 AddPolicyRegistry() 方法是 IServiceCollection 的一个扩展方法。它将创建一个新的 PolicyRegistry 并以接口 IPolicyRegistry<string> 和 IReadOnlyPolicyRegistry<string> 的实现注册到 DI 容器中。该方法返回策略,可以通过它添加策略到其中。

在下面的示例中,我们添加了两个超时策略并命名。然后,在注册客户端的时候,我们可以调用 AddPolicyHandlerFromREgistry() 方法,它在 IHttpClientBuilder 上。它使用我们希望使用的策略名称。当工厂创建该命名的客户端的时候,它将称为 "regular" 的重试策略添加适当的处理器。

var registry = services.AddPolicyRegistry();

var timeout = Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(10));
var longTimeout = Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(30)); registry.Add("regular", timeout);
registry.Add("long", longTimeout); services.AddHttpClient("github")
.AddPolicyHandlerFromRegistry("regular");

总结

随着长时间使用 Polly,我非常高兴地看到它被集成到 IHttpClientFactory 中。这些库合起来使得很容易设置并一起使用,HttpClient 实例可以流畅地处理瞬时失效。我们展示的示例很基本和通用。但是,我希望它们可以提供策略是如何使用和注册的思路。更多的 Polly 文档和示例,我建议你查阅 Polly 的 Wiki 页面。

Part 1 – HttpClientFactory in ASP.NET Core 2.1 Part 1 介绍

Part 2 – HttpClientFactory in ASP.NET Core 2.1 Part 2:定义命名和类型化的客户端

Part 3 – HttpClientFactory in ASP.NET Core 2.1 Part 3: 对处理器使用对外请求中间件

Part 4 – HttpClientFacotry Part 4: 集成 Polly 处理瞬时失效

Part 5 – HttpClientFactory in ASP.NET Core 2.1 Part 5: 日志

HttpClientFacotry Part 4: 集成 Polly 处理瞬时失效的更多相关文章

  1. ASP.Net Core2.1中的HttpClientFactory系列二:集成Polly处理瞬态故障

    前言:最近,同事在工作中遇到了使用HttpClient,有些请求超时的问题,辅导员让我下去调研一下,HttpClinet的使用方式已经改成了之前博客中提到的方式,问题的原因我已经找到了,就是因为使用了 ...

  2. ASP.NET Core 2.1 中的 HttpClientFactory (Part 4) 整合Polly实现瞬时故障处理

    原文:https://www.stevejgordon.co.uk/httpclientfactory-using-polly-for-transient-fault-handling发表于:2018 ...

  3. spring集成shiro,事务失效问题 not eligible for auto-proxying

    BeanPostProcessor bean实例化顺序有关,@Configuration会最先实例化,也就是在spring启动完成之前. 导致Configuration中使用的注入,没能在spring ...

  4. NetCore项目实战篇07---服务保护之polly

    1.  为什么要用polly 前面的项目中,一个服务调用另一个(Zhengwei.Identity调用Zhengwei.Use.Api)服务时是直接调用的,在这个调用的过程中可能会发生各种瞬态故障,这 ...

  5. oracle asm 概念

    automated storage management ,即自动存储管理,简称asm .. 在oracle 10g 这个版本之前,管理一个大型数据库成千上万的数据文件对数据库管理员来说是一个既无技术 ...

  6. MTBF

    MTBF,即平均故障间隔时间,英文全称是"Mean Time Between Failure".是衡量一个产品(尤其是电器产品)的可靠性指标.单位为"小时".它 ...

  7. HttpClient在.NET Core中的正确打开方式

    问题来源 长期以来,.NET开发者都通过下面的方式发送http请求: using (var httpClient = new HttpClient()) { var response = await ...

  8. asp.net core microservices 架构之eureka服务发现

    一 简介 微服务将需多的功能拆分为许多的轻量级的子应用,这些子应用相互调度.好处就是轻量级,完全符合了敏捷开发的精神.我们知道ut(单元测试),不仅仅提高我们的程序的健壮性,而且可以强制将类和方法的设 ...

  9. 手动造轮子——基于.NetCore的RPC框架DotNetCoreRpc

    前言     一直以来对内部服务间使用RPC的方式调用都比较赞同,因为内部间没有这么多限制,最简单明了的方式就是最合适的方式.个人比较喜欢类似Dubbo的那种使用方式,把接口层单独出来,作为服务的契约 ...

  10. 网关Ocelot功能演示安排的明明白白~~~

    前言 网关(Gateway)在微服务架构中至关重要,可以将其理解为是外部客户端(前端.MVC后台等调用方)与后台服务的连接点,通过这层可以做统一的处理,比如路由.身份认证和授权.服务治理等: 网关的好 ...

随机推荐

  1. composer 执行脚本时报错:Error: You made a reference to a non-existent script @php artisan package:discover

    composer 执行脚本时报错:Error: You made a reference to a non-existent script @php artisan package:discover. ...

  2. Linux 系统常见 的命令

    uname -a 查看linux 的版本信息 : pwd :打印当前的工作目录 ,print work directory: cd  改变目录 ,change directory : cd . 当前目 ...

  3. kotlin关键字与操作符

    硬关键字:始终解释为关键字,不能用作标识符 as - 用于类型转换 - 为导入指定一个别名 as? 用于安全类型转换 break 终止循环的执行 class 声明一个类 continue 继续最近层循 ...

  4. 在 K8s 中快速部署使用 GitLab 并构建 DevOps 项目

    作者:张海立,KubeSphere 社区 Ambassador.Talented Speaker,社区用户委员会上海站副站长 原文链接:https://kubesphere.com.cn/blogs/ ...

  5. [图像处理] 基于CleanVision库清洗图像数据集

    CleanVision是一个开源的Python库,旨在帮助用户自动检测图像数据集中可能影响机器学习项目的常见问题.该库被设计为计算机视觉项目的初步工具,以便在应用机器学习之前发现并解决数据集中的问题. ...

  6. 洛谷 P1328 [NOIP2014 提高组] 生活大爆炸版石头剪刀布

    题目大意 小A和小B,要进行 \(N\) 次猜拳,每次按照一定周期出拳,胜负情况如下: 求出小A和小B分别赢了几次. 思路 枚举 \(N\) 次猜拳,每次比较 \(a[powera]\) 与 \(b[ ...

  7. ubuntu16.04安装mmdetection库

    一,前言 1.1,更新 pip 和 conda下载源 1.2,查看 conda 和 pip 版本 二,MMDetection 简介 三,MMDetection 安装 3.1,依赖环境 3.2,安装过程 ...

  8. Java面试题中高级进阶(JVM篇Java内存)

    前言 本来想着给自己放松一下,刷刷博客,突然被几道面试题难倒!说说Java内存结构?说说对象分配规则?描述一下JVM加载class文件的原理机制?似乎有点模糊了,那就大概看一下面试题吧.好记性不如烂键 ...

  9. Codeforces 2023/2024 A-H

    题面 A B C D E F G H 难度:红 橙 黄 绿 蓝 紫 黑 黑 题解 A 题目大意: 输入 \(a\),\(b\),解不等式 \(b - 2x \le a - x (0 \le x \le ...

  10. 案例分享-导致MySQL崩溃的SQL语句

    背景 周一刚上班一个开发小哥火急火燎的过来找我,黑龙江某客户私有化环境的服务过一阵就报数据库连接失败,不知道是什么原因导致的,我以为是客户调整了网络,但是客户说并没有做任何调整,我使用ping测试也看 ...