Flurl使用Polly实现重试Policy

在使用Flurl作为HttpClient向Server请求时,由于网络或者其它一些原因导致请求会有失败的情况,比如HttpStatusCode.NotFoundHttpStatusCode.ServiceUnavailable、HttpStatusCode.RequestTimeout等;网络上有比较多的HttpClientFactory使用Polly来实现重试的内容,奈何已经习惯使用Flurl的人,要全部换回到IHttpClient的确有不方便的地方,因为本文使用Flurl的Polly来实现重试机制做一个整理;

不使用Polly来测试

  1. 提供一个接口以便做请求测试

    [Route("api/[controller]")]
    [ApiController]
    public class PollyController : ControllerBase
    {private readonly ILogger<PollyController> _logger;public PollyController(ILogger<PollyController> logger){_logger = logger;}// GET: api/<PollyController>[HttpGet]public IActionResult Get(){var random = new Random().Next(0, 8);switch (random){case 0:_logger.LogInformation("About to serve a 404");return StatusCode(StatusCodes.Status404NotFound);case 1:_logger.LogInformation("About to serve a 503");return StatusCode(StatusCodes.Status503ServiceUnavailable);case 2:_logger.LogInformation("Sleeping for 10 seconds then serving a 504");Thread.Sleep(10000);_logger.LogInformation("About to serve a 504");return StatusCode(StatusCodes.Status504GatewayTimeout);default:_logger.LogInformation("About to correctly serve a 200 response");return Ok(new {time = DateTime.Now.ToLocalTime()});}}
    }
    
  2. 创建一个请求客户端

    public class HomeController : Controller
    {private readonly ILogger<HomeController> _logger;public HomeController(ILogger<HomeController> logger){_logger = logger;}public async Task<IActionResult> Index(){try{var time = await "http://127.0.0.1:5000/api/polly".GetJsonAsync();_logger.LogInformation($"App: success - {time.time}");return View(time.time);}catch (Exception e){_logger.LogWarning($"App: failed - {e.Message}");throw;}}
    }
    
  3. 尝试请求,可以发现有很多请求失败的地方,这个情况很不理想,服务器有较大的机率不能正常的响应

    info: SuppertRcsInterfaceTest.Controllers.PollyController[0]About to serve a 404
    info: SuppertRcsInterfaceTest.Controllers.PollyController[0]About to correctly serve a 200 response
    info: SuppertRcsInterfaceTest.Controllers.PollyController[0]About to correctly serve a 200 response
    info: SuppertRcsInterfaceTest.Controllers.PollyController[0]About to correctly serve a 200 response
    info: SuppertRcsInterfaceTest.Controllers.PollyController[0]About to serve a 503
    info: SuppertRcsInterfaceTest.Controllers.PollyController[0]About to serve a 503
    info: SuppertRcsInterfaceTest.Controllers.PollyController[0]About to correctly serve a 200 response
    info: SuppertRcsInterfaceTest.Controllers.PollyController[0]About to serve a 404
    

    针对这个情况有没有什么解决的办法呢,答案是肯定的,粗暴的想法就是失败了再重新做请求,直接在Flurl的返回结果中做这个逻辑处理会比较麻烦也不方便统一的管理,如此就找到了Polly

使用Polly来测试

  1. 首先安装Polly, Install-Package Polly

  2. 下面先给出Polly的简单介绍后接着给出Policy的代码片段

    Polly的七种策略:重试、断路、超时、隔离、回退和缓存策略,本文使用到了重试、超时策略

    重试(Retry):出现故障自动重试,这个是常见的场景

    断路(Circuit-breaker):当系统遇到严重的问题时,快速回馈失败比让用户/调用者等待要好,限制系统出错的消耗,有助于系统恢复,比如,当我们去调用一个第三方的API,有很长一段时间API都没有响应,可能对方服务器瘫痪了,如果我们的系统还不停地重试,不仅会加重系统的负担,还有可能导致系统其它任务受影响,因此,当系统出错的次数超过了指定的阈值,就得中断当前线程,等待一段时间后再继续;比如: Policy.Handle<SomeException>().CircuitBreaker(2, TimeSpan.FromMinutes(1));表示当系统出现两次某个异常时就停下来,等待1分钟后再继续,还可以在断路时定义中断的回调和重启的回调。

    超时(Timeout):当系统超过一定时间的等待,就可以判断不可能会有成功的结果;比如平时一个网络请求瞬间就完成了,如果有一次网络请求超过了30秒还没有完成,我们就可以判定不可能会返回成功的结果了,因此,我们需要设置系统的超时时间,避免系统长时间无谓的等待;比如:Policy.Timeout(30, (context, span, task) => {// do something});表示设置了超时时间不能超过30秒,否则就认为是错误的结果,并执行回调。

    隔离(Bulkhead Isolation):当系统的一处出现故障时,可能触发多个失败的调用,对资源有较大的消耗,下游系统出现故障可能导致上游的故障的调用,甚至可能蔓延到导致系统崩溃,所以要将可控的操作限制在一个固定大小的资源池中,以隔离有潜在可能相互影响的操作;比如:Policy.Bulkhead(12, context => {// do something});表示最多允许12个线程并发执行,如果执行被拒绝,则执行回调。

    回退(Fallback):有些错误无法避免,就要有备用的方案,当无法避免的错误发生时,我们要有一个合理的返回来代替失败;比如:Policy.Handle<Whatever>().Fallback<UserAvatar>(() => UserAvatar.GetRandomAvatar());表示当用户没有上传头像时,我们就给他一个默认头像。

    缓存(Cache):一般我们会把频繁使用且不会怎么变化的资源缓存起来,以提高系统的响应速度,如果不对缓存资源的调用进行封装,那么我们调用的时候就要先判断缓存中有没有这个资源,有的话就从缓存返回,否则就从资源存储的地方获取后缓存起来再返回,而且有时还要考虑缓存过期和如何更新缓存的问题;Polly提供了缓存策略的支持,使得问题变得简单。

    策略包(Policy Wrap):一种操作会有多种不同的故障,而不同的故障处理需要不同的策略,这些不同的策略必须包在一起,作为一个策略包,才能应用在同一种操作上,这就是Polly的弹性特性,即各种不同的策略能够灵活地组合起来

    更多...

    using System;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Threading;
    using System.Threading.Tasks;
    using Flurl.Http.Configuration;
    using Microsoft.Extensions.Logging;
    using Polly;
    using Polly.Retry;
    using Polly.Timeout;
    using Polly.Wrap;namespace WithPollyClient.Services
    {public class Policies{private readonly ILogger<Policies> _logger;public Policies(ILogger<Policies> logger){_logger = logger;}private AsyncTimeoutPolicy<HttpResponseMessage> TimeoutPolicy{get{return Policy.TimeoutAsync<HttpResponseMessage>(3, (context, span, task) =>{_logger.LogInformation($"Policy: Timeout delegate fired after {span.Seconds} seconds");return Task.CompletedTask;});}}private AsyncRetryPolicy<HttpResponseMessage> RetryPolicy{get{HttpStatusCode[] retryStatus ={HttpStatusCode.NotFound,HttpStatusCode.ServiceUnavailable,HttpStatusCode.RequestTimeout};return Policy.HandleResult<HttpResponseMessage>(r => retryStatus.Contains(r.StatusCode)).Or<TimeoutRejectedException>().WaitAndRetryAsync(new[]{// 表示重试3次,第一次1秒后重试,第二次2秒后重试,第三次4秒后重试TimeSpan.FromSeconds(1),TimeSpan.FromSeconds(2),TimeSpan.FromSeconds(4)}, (result, span, count, context) =>{_logger.LogInformation($"Policy: Retry delegate fired, attempt {count}");});}}public AsyncPolicyWrap<HttpResponseMessage> PolicyStrategy =>Policy.WrapAsync(RetryPolicy, TimeoutPolicy);}public class PolicyHandler : DelegatingHandler{private readonly Policies _policies;public PolicyHandler(Policies policies){_policies = policies;}protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken){return _policies.PolicyStrategy.ExecuteAsync(ct => base.SendAsync(request, ct), cancellationToken);}}public class PollyHttpClientFactory : DefaultHttpClientFactory{private readonly Policies _policies;public PollyHttpClientFactory(Policies policies){_policies = policies;}public override HttpMessageHandler CreateMessageHandler(){return new PolicyHandler(_policies){InnerHandler = base.CreateMessageHandler()};}}
    }
    
  3. 接下来在Starup中对Flurl进行配置

    public void ConfigureServices(IServiceCollection services)
    {services.AddControllersWithViews();services.AddSingleton<Policies>();
    }// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {var policies = app.ApplicationServices.GetService<Policies>();FlurlHttp.Configure(setting =>setting.HttpClientFactory = new PollyHttpClientFactory(policies));......
    
  4. 再次尝试请求,可以看到结果非常之理想

    WithPollyClient.Services.Policies: Information: Policy: Retry delegate fired, attempt 1
    WithPollyClient.Controllers.HomeController: Information: App: success - 2021/3/14 16:50:14
    WithPollyClient.Services.Policies: Information: Policy: Retry delegate fired, attempt 1
    WithPollyClient.Controllers.HomeController: Information: App: success - 2021/3/14 16:50:17
    WithPollyClient.Controllers.HomeController: Information: App: success - 2021/3/14 16:50:22
    WithPollyClient.Controllers.HomeController: Information: App: success - 2021/3/14 16:50:23
    WithPollyClient.Services.Policies: Information: Policy: Retry delegate fired, attempt 1
    WithPollyClient.Controllers.HomeController: Information: App: success - 2021/3/14 16:50:25
    WithPollyClient.Controllers.HomeController: Information: App: success - 2021/3/14 16:50:31
    WithPollyClient.Services.Policies: Information: Policy: Retry delegate fired, attempt 1
    WithPollyClient.Controllers.HomeController: Information: App: success - 2021/3/14 16:50:34
    WithPollyClient.Controllers.HomeController: Information: App: success - 2021/3/14 16:50:39
    WithPollyClient.Services.Policies: Information: Policy: Retry delegate fired, attempt 1
    WithPollyClient.Services.Policies: Information: Policy: Timeout delegate fired after 3 seconds
    WithPollyClient.Services.Policies: Information: Policy: Retry delegate fired, attempt 2
    WithPollyClient.Controllers.HomeController: Information: App: success - 2021/3/14 16:50:46
    

富客户端中使用的情况

有时候呢,例如在WPF或者是其它的富客户端上面也会经常使用到Flurl的情况,如下

var time = await Policy.Handle<FlurlHttpException>().OrResult<IFlurlResponse>(r => !r.ResponseMessage.IsSuccessStatusCode).WaitAndRetryAsync(new[]{TimeSpan.FromSeconds(1),TimeSpan.FromSeconds(2),TimeSpan.FromSeconds(4)}, (result, span, count, context) =>{_logger.LogInformation(count.ToString());}).ExecuteAsync(() => "http://127.0.0.1:5000/api/polly".WithTimeout(3).GetAsync()).ReceiveJson();_logger.LogInformation($"App: success - {time.time}");
return View(time.time);

时间如流水,只能流去不流回。

  • 公众号:Dotnet9

  • 号主微信号:dotnet9

  • 作者:非法关键字

  • 原文:Flurl使用Polly添加重试机制

  • 编辑:沙漠之尽头的狼

  • 日期:2021-03-15

微信公众号:Dotnet9

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/303940.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

推荐15个 JavaScript 和 CSS 库

Tutorialzine的使命是让开发者与最新的Web开发发展同步。因此&#xff0c;我们每月都会精选一批最优秀的资源推荐给大家&#xff0c;相信这些资源你绝对值得拥有&#xff01;ClarifyJSClarifyJS可以让你串联一串方法&#xff0c;以任意顺序执行。通常的JavaScript方法是从左到右…

Dapr Meetup 3.22【周六】

点击蓝字关注我们Dapr&#xff08;Distributed Application Runtime &#xff0c;分布式应用运行时&#xff09;是微软新推出的&#xff0c;一个可移植的、由事件驱动的运行时&#xff0c;用于跨云和边缘构建分布式应用程序。2019年10月9日&#xff0c;正式以 MIT 协议开源。…

日本老爷爷坚持17年用Excel作画,我可能用了假的Excel···

本文来源自网络说起办公软件Excel&#xff0c;不少人可能同小编一样&#xff0c;谈及色变。想想公式、表格头都大了&#xff0c;今天要介绍的这个人竟然可以用其作画&#xff0c;简直是大写的“丧心病狂”&#xff01;这位传奇人物就是堀内辰男&#xff0c;今年已经77岁了&…

腾讯二面挂了,就因为这个...

牛年跳槽季&#xff0c;惨遭开门黑&#xff0c;谨以此文纪念我的首次腾讯面试经历。经我的老师&#xff0c;微软MVP大佬推荐&#xff0c;有幸拿到了腾讯.NET Core高开面试机会&#xff0c;二面却挂在一个最常见的问题上&#xff0c;“你上家公司电商平台的TPS、QPS是多少&#…

51CTO博客 NO.1 大奖赛之后感想---奖品

自从加入51cto技术成就梦想这个大家庭以来&#xff0c;进入这个大家庭可以说是个机会&#xff0c;也可以是个缘分&#xff1b;已经有半年了&#xff0c;明朗炽热般的心&#xff0c;使我深深地喜欢上了这一个大家庭&#xff1b;这个大家庭是一个很不平凡而又富有源源不断学而不尽…

入门 | 我们常听说的置信区间与置信度到底是什么?

机器学习本质上是对条件概率或概率分布的估计&#xff0c;而这样的估计到底有多少是置信度&#xff1f;这里就涉及到统计学里面的置信区间与置信度&#xff0c;本文简要介绍了置信区间这一核心概念&#xff0c;它有助于我们从直观上理解评价估计优劣的度量方法。本文讨论了统计…

.NET 差点不叫“.NET”?微软大牛爆料技术往事

作者 | 伍杏玲出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;2000 年注定是不平凡的一年&#xff1a;千年虫问题爆发、互联网泡沫破灭……正值世界风云突变之际&#xff0c;比尔盖茨和史蒂夫鲍尔默向全球宣布全力打造“下一代因特网”——.NET 平台。比尔盖茨对.N…

【翻译】WPF 中附加行为的介绍 Introduction to Attached Behaviors in WPF

【翻译】WPF 中附加行为的介绍 Introduction to Attached Behaviors in WPF目录 隐藏 引言 [Introduction]背景 [Background]附加行为 [Attached Behaviors]论证 [Demonstration]结论 [Conclusion]参考 [References]版本历史 [Revision History]许可证 [License]作者&#xff…

地图是怎么知道实时路况的?因为我们每个人都是“百万年薪级”数据贡献者

【导读】地图公司给地图“上色”主要靠数据&#xff0c;数据够则地图生。数据是地图的生命&#xff0c;车速是路况的根本&#xff0c;地图获取数据主要有两种方式&#xff1a;自给自足、仰给于人上班出门&#xff0c;点开地图&#xff0c;前面红色&#xff0c;后面红色&#xf…

MySQL优化从执行计划开始(explain超详细)

前言小伙伴一定遇到过这样反馈&#xff1a;这页面加载数据太慢啦&#xff0c;甚至有的超时了&#xff0c;用户体验极差&#xff0c;需要赶紧优化&#xff1b;反馈等同于投诉啊&#xff0c;多有几次&#xff0c;估计领导要找你谈话啦。于是不得不停下手里头的活&#xff0c;赶紧…

一个老程序员的忠告:不要一辈子靠技术生存

图丨《Ready Player One》文丨源&#xff1a;世界经理人我现在是自己做&#xff0c;但我此前有多年在从事软件开发工作&#xff0c;当回过头来想一想自己&#xff0c;觉得特别想对那些初学JAVA/DOT。NET技术的朋友说点心里话&#xff0c;希望你们能从我们的体会中&#xff0c;多…

怎样安装php52-71,CentOS如何安装PHP5和PHP7

推荐(免费)&#xff1a;PHP7安装PHP5下载解压二进制包[roottest-a src]# cd /usr/local/src/[roottest-a src]# wget http://cn2.php.net/distributions/php-5.6.32.tar.bz2[roottest-a src]# tar jxvf php-5.6.32.tar.bz2编译安装PHP./configure --prefix/usr/local/php --wit…

应用程序自动更新组件GeneralUpdate3.2.1发布

GeneralUpdate开源组件更新公告一、组件简介GeneralUpdate是基于.net standard开发的一款&#xff08;c/s应用&#xff09;自动升级程序。该组件将更新的核心部分抽离出来方便应用于多种项目当中目前适用于wpf&#xff0c;控制台应用&#xff0c;winfrom。本组件&#xff08;除…

你不知道C#只带有 get 访问器的属性是只读属性?

问题窥探之前有个哥们在使用Newtonsoft.Json反序列化的时候&#xff0c;发现明明有数据&#xff0c;但是就是序列化不出来数据到实体里面。咋一看&#xff0c;确实没什么问题啊&#xff0c;字符串的数据是存在的。那么问题出在哪里呢。解决思路1、我让他把字符串复制出来&#…

葬身李刚儿子车轮下的漂亮女孩

这么一个青春、靓丽的女孩~~~~~~~~就这样丧生在官二代的铁轮下~~~~~~~~~~~~可惜了~~~~~~~~~~~~哀痛啊&#xff0c;什么世道&#xff01;转载于:https://blog.51cto.com/jsfido/418494

RTC 媒体流数据包丢包问题解决

最近在一个测试中&#xff0c;遇到了OCS和PSTN通话之间的声音出现严重的断续问题&#xff0c;用户的使用体验就是听对方的声音不是完整的&#xff0c;有部分的语音丢失&#xff0c;在服务器上判断就是RTC数据包丢失了。专业术语就是Voice clipping。先看看丢包的恐怖情况&#…

如何在 ASP.Net Core 中使用 Autofac

依赖注入可以有效的实现对象之间的 松耦合 并能够实现代码的可测试和可维护性&#xff0c;ASP.Net Core 提供了一个极简版的容器实现对 依赖注入 的原生支持&#xff0c;然而内置的依赖注入容器相比成熟的 依赖注入容器 太弱了。为了解决这个问题&#xff0c;可以使用第三方的依…

2010年11月编程语言排行榜:手机里的代码

【51CTO独家特稿】Tiobe今天发布了最新一期的编程语言排行榜。本期榜单的前五名与10月份没有明显变化&#xff0c;依然是Java、C、C、PHP和Python&#xff1b;Objective-C的增长势头强劲。本期另外一个值得注意的语言是重回前20名NXT-G。NXT-G是一种集成在乐高&#xff08;LEGO…

NET问答: 如何迭代 Enum ?

咨询区 Peter Mortensen&#xff1a;如何使用 C# 迭代 enum ?下面的代码会编译失败&#xff0c;错误信息: Suit is a type but is used like a variablepublic enum Suit {Spades,Hearts,Clubs,Diamonds }public void EnumerateAllSuitsDemoMethod() {foreach (Suit suit in S…

承接数字油画图稿/线条图定制(出图)业务

集异璧实验室对外提供数字油画图纸&#xff08;图稿/线条图&#xff09;定制和自选业务&#xff0c;欢迎洽谈。 定制流程&#xff1a; &#xff08;1&#xff09;贵方将图片传给我方&#xff1b; &#xff08;2&#xff09;我方出图&#xff0c;提供效果图&#xff1b; &#…