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,一经查实,立即删除!

相关文章

Linux下判断cpu物理个数、几核

自己服务器的输出 1. 查看物理CPU的个数 #cat /proc/cpuinfo |grep "physical id"|sort |uniq|wc -l12. 查看逻辑CPU的个数#cat /proc/cpuinfo |grep "processor"|wc -l83. 查看CPU是几核#cat /proc/cpuinfo |grep "cores"|uniqcpu cores : 44.…

java并发框架支持锁包括,jdk1.8锁

JDK1.8有什么锁?_李广进的博客-CSDN博客2020年4月23日 18、排他锁(不包含),X锁,若事务T对数据对象A加上x锁,则只允许T读取和修改A,其他任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。这就保证了其他...jdk1.8对锁进行了哪些优化? - 知乎2020年1月8日 关注问题​写回答…

推荐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 协议开源。…

iPhone Development Blog系列: 如何制作服务条例窗口

iPhone Development Blog系列: 如何制作服务条例窗口 最近一直关注iPhone Development Blog上面的文章&#xff0c;学习的同时尝试通过翻译和整理同大家一起分享&#xff01; 假设你想让你的每个客户在使用iPhone应用前接受你的服务条例&#xff08;Terms of Services&#xff…

用matlab算24点小游戏,24点游戏的Matlab程序

function GUI_games24S.fh figure(units,pixels,...position,[500 500 800 200],...menubar,none,...name,24点游戏,...numbertitle,off,...resize,off);S.ti uicontrol(style,text,...units,pix,...position,[300 150 180 30],...string,24点的计算程序,fontsize,15);S.ra u…

日本老爷爷坚持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;这个大家庭是一个很不平凡而又富有源源不断学而不尽…

php defunct,通过swoole观察僵尸进程和孤儿进程出现和消亡

声明&#xff1a;维基百科上没有僵死进程的词条&#xff0c;这里认为僵死进程同僵尸进程&#xff0c;即ZOMBIE。一、定义什么是僵尸进程维基百科的定义&#xff1a;在类UNIX系统中&#xff0c;僵尸进程是指完成执行(通过exit系统调用&#xff0c;或运行时发生致命错误或收到终止…

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

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

【谷歌】Google Chrome 浏览器中 font-size 12px 没有效果

Google Chrome 浏览器中 font-size < 12px 没有效果 解决方法&#xff1a; *&#xff5b;-webkit-text-size-adjust: none;&#xff5d; 此功能立竿见影&#xff0c;目的是去掉CHROME的自动调整字体大小&#xff0c;显示比12PX小的字体。转载于:https://www.cnblogs.com/cos…

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

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

php获取昨日时间段内,PHP 获取 特定时间范围 类

1 <?php2 /**3 * Created by PhpStorm.4 * Author: 林冠宏5 * Date: 2016/6/46 * Time: 16:067 *8 * 前序&#xff1a;9 * 总体来说&#xff0c;我更应该是一个 android 移动开发者&#xff0c;而不是一个 phper&#xff0c;如果说只做移动端的 APP &#xff0c;10 * 我也不…

【翻译】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…

matlab行程编码,报告论文:游程(行程)长度编码matlab(或者C++)实现

游程(行程)长度编码matlab(或者C)实现html我须要的是算法实现,好比说我输入序列{1,0,0,0,0,1,1},输出为{11,04,12}.后面输出结果的含义是,"11"表示1的个数为1,"04"表示后面连续0的个数为4,"11"表示最后面出现连续1的次数为2次ios#include算法#in…

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

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

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

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

大端(Big Endian)、小端(Little Endian)

端模式&#xff08;Endian&#xff09;的这个词出自Jonathan Swift书写的《格列佛游记》。这本书根据将鸡蛋敲开的方法不同将所有的人分为两类&#xff0c;从圆头开始将鸡蛋敲开的人被归为Big Endian&#xff0c;从尖头开始将鸡蛋敲开的人被归为Littile Endian。小人国的内战就…