HttpClientFacotry Part 4: 集成 Polly 处理瞬时失效
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 处理瞬时失效的更多相关文章
- ASP.Net Core2.1中的HttpClientFactory系列二:集成Polly处理瞬态故障
前言:最近,同事在工作中遇到了使用HttpClient,有些请求超时的问题,辅导员让我下去调研一下,HttpClinet的使用方式已经改成了之前博客中提到的方式,问题的原因我已经找到了,就是因为使用了 ...
- ASP.NET Core 2.1 中的 HttpClientFactory (Part 4) 整合Polly实现瞬时故障处理
原文:https://www.stevejgordon.co.uk/httpclientfactory-using-polly-for-transient-fault-handling发表于:2018 ...
- spring集成shiro,事务失效问题 not eligible for auto-proxying
BeanPostProcessor bean实例化顺序有关,@Configuration会最先实例化,也就是在spring启动完成之前. 导致Configuration中使用的注入,没能在spring ...
- NetCore项目实战篇07---服务保护之polly
1. 为什么要用polly 前面的项目中,一个服务调用另一个(Zhengwei.Identity调用Zhengwei.Use.Api)服务时是直接调用的,在这个调用的过程中可能会发生各种瞬态故障,这 ...
- oracle asm 概念
automated storage management ,即自动存储管理,简称asm .. 在oracle 10g 这个版本之前,管理一个大型数据库成千上万的数据文件对数据库管理员来说是一个既无技术 ...
- MTBF
MTBF,即平均故障间隔时间,英文全称是"Mean Time Between Failure".是衡量一个产品(尤其是电器产品)的可靠性指标.单位为"小时".它 ...
- HttpClient在.NET Core中的正确打开方式
问题来源 长期以来,.NET开发者都通过下面的方式发送http请求: using (var httpClient = new HttpClient()) { var response = await ...
- asp.net core microservices 架构之eureka服务发现
一 简介 微服务将需多的功能拆分为许多的轻量级的子应用,这些子应用相互调度.好处就是轻量级,完全符合了敏捷开发的精神.我们知道ut(单元测试),不仅仅提高我们的程序的健壮性,而且可以强制将类和方法的设 ...
- 手动造轮子——基于.NetCore的RPC框架DotNetCoreRpc
前言 一直以来对内部服务间使用RPC的方式调用都比较赞同,因为内部间没有这么多限制,最简单明了的方式就是最合适的方式.个人比较喜欢类似Dubbo的那种使用方式,把接口层单独出来,作为服务的契约 ...
- 网关Ocelot功能演示安排的明明白白~~~
前言 网关(Gateway)在微服务架构中至关重要,可以将其理解为是外部客户端(前端.MVC后台等调用方)与后台服务的连接点,通过这层可以做统一的处理,比如路由.身份认证和授权.服务治理等: 网关的好 ...
随机推荐
- 关于pytorch中@和*的用处
1.@是用来对tensor进行矩阵相乘的: import torch d = 2 n=50 X = torch.randn(n,d) true_w = torch.tensor([[-1.0],[2. ...
- Java实用小工具系列1---使用StringUtils分割字符串
经常有这种情况,需要将逗号分割的字符串,比如:aaa, bbb ,ccc,但往往是人工输入的,难免会有多空格逗号情况,比如:aaa, bbb , ccc, ,,这种情况使用split会解析出不正常的结 ...
- C# 新语法 switch 的简单写法
// C# 中的新语法 switch 的简写 string str = "123"; string res = str switch { "1" => & ...
- yarn 和 npm 不能混合使用
当有 yarn.lock 的时候说明项目使用的yarn 创建的 则后面的都要使用 yarn 操作,比如下载 包 等 : 当项目没有 yarn.lock 而是 package.json.lock 说明项 ...
- 新手入门使用pinia
.markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rg ...
- 云原生周刊:Kubernetes Grafana 看板更新 | 2024.5.13
开源项目推荐 Chart Testing Chart Testing 是用于测试 Helm 图表的工具.它旨在用于对拉取请求进行 lint 和测试.它会自动检测针对目标分支更改的图表. Cluster ...
- 云原生周刊:Kubernetes v1.28 正式发布 | 2023.8.21
开源项目推荐 kurt 一个 Kubernetes 插件,可提供 Kubernetes 集群中重启内容的上下文信息. Kubean Kubean 是一个基于 kubespray 的 Kubernete ...
- Java面试真题之中级进阶(线程,进程,序列化,IO流,NIO)
前言 本来想着给自己放松一下,刷刷博客,慕然回首,线程.程序.进程?Java 序列化?Java 中 IO 流? Java IO与 NIO的区别(补充)?似乎有点模糊了,那就大概看一下Java基础面试题 ...
- MySQL修改用户权限
最近测试中台的存储服务,涉及到MySQL用户操作的命令,记录一下. 1.查看所有用户 select user from mysql.user; 2.查看当前登陆用户 select user(); 3. ...
- 对比 Unittest 和 Pytest
一.用例编写规则 1,Unittest提供了test cases.test suites.test fixtures.test runner相关的类,让测试更加明确.方便.可控.使用unittest编 ...