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后台等调用方)与后台服务的连接点,通过这层可以做统一的处理,比如路由.身份认证和授权.服务治理等: 网关的好 ...
随机推荐
- 从url地址获取主机名
function getHost(url) { var host = "null"; if(typeof url == "undefined"|| null = ...
- 49.var声明的函数和function声明的函数谁的优先级更高
function 声明函数的优先级更高 : 因为 function声明函数的时候,是在代码解析之前赋值给变量,此时就已经可以调用了 : 但是var 声明的函数,要在代码运行阶段才会赋值给变量,这个时候 ...
- nodejs 和 npm 版本对应关系
一.nodejs 和 npm 的版本是有适配的 首先看下官网列明的大概匹配关系: 官网链接地址:https://nodejs.org/zh-cn/about/previous-releases 可以查 ...
- OpenFunction 成为 CNCF 沙箱项目,使 Serverless 函数与应用运行更简单
2022 年 4 月 27 日,青云科技容器团队开源的函数即服务(FaaS: Function-as-a-Service)项目 OpenFunction 顺利通过了云原生计算基金会 CNCF 技术监督 ...
- Unity 华为快游戏JS桥接 实现写日志等功能
之前接入微信小游戏本身代码js桥接比较完善,抖音小游戏有缺少但也没缺的这么多,华为这边的API,大残啊!官方转换插件Github仓库上一次提交在3月份.(截至现在)API给的很简略,接入js代码那里说 ...
- 用Qt发布打包的应用程序
使用Qt Creator创建Realase版本的程序之后,我们的程序可以正常运行,但是在没有Qt的电脑里是无法运行的. 原因说的很清楚,缺少了动态库.所以我们要把其他需要的库打包进来一起发布才可以.Q ...
- 线性规划(LP)问题
约束最优化--线性规划(LP)问题 1 线性规划 1.1 图解法(计算机不适用,便于理解) 1.2 单纯形法 1.3 计算几何的方法(待更新) 1 线性规划 约束优化问题:给定约束条件和目标函数,计算 ...
- 面试真题:OOM(OutOfMemoryError)SOF(StackOverflow)你遇到过哪些情况
前言 本来想着给自己放松一下,刷刷博客,慕然回首,OOM?SOF?似乎有点模糊了,那就大概看一下Java面试题吧.好记性不如烂键盘 *** 12万字的java面试题整理 *** OOM你遇到过哪些情况 ...
- MyBatis-Plus条件构造器:构建安全、高效的数据库查询
一.关于条件构造器(Wrapper) 1.1 简介 MyBatis-Plus 提供了一套强大的条件构造器(Wrapper),用于构建复杂的数据库查询条件.Wrapper 类允许开发者以链式调用的方式构 ...
- 多校A层冲刺NOIP2024模拟赛18
多校A层冲刺NOIP2024模拟赛18 T1 选彩笔(rgb) 签到题,但是没签上... 没想到三维前缀和,直接上了个bitset. 就是直接二分答案,然后枚举这三维每维的区间的起点,前缀和查数量是否 ...