.Net Core 商城微服务项目系列(五):使用Polly处理服务错误
项目进行微服务化之后,随之而来的问题就是服务调用过程中发生错误、超时等问题的时候我们该怎么处理,比如因为网络的瞬时问题导致服务超时,这在我本人所在公司的项目里是很常见的问题,当发生请求超时问题的时候,我们希望能够自动重试,或者是在发生服务错误时采取一定的策略,比如限流熔断等等。
本篇将会使用Polly处理服务调用过程中发生的超时问题。
打开我们的MI.Web项目,通过NuGet引用 Microsoft.Extensions.Http 和 Microsoft.Extensions.Http.Polly。
在Startup中添加如下代码:
- public static class ServiceCollectionExtensions
- {
- public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration)
- {
//依赖注入- services.AddSingleton<IApiHelperService, ApiHelperService>();
- services.AddSingleton<IAccountService, AccountService>();
- services.AddSingleton<IPictureService, PictureService>();
- services.AddOptions();
- services.AddMvc(options =>
- {
- options.Filters.Add<HttpGlobalExceptionFilter>();
- });
- services.AddMemoryCache();
- services.AddCors(options =>
- {
- options.AddPolicy("CorsPolicy",
- builder => builder.AllowAnyOrigin()
- .AllowAnyMethod()
- .AllowAnyHeader()
- .AllowCredentials());
- });
- return services;
- }
- public static IServiceCollection AddHttpServices(this IServiceCollection services)
- {//注册http服务
- //services.AddHttpClient();
- services.AddHttpClient("MI")
- .AddPolicyHandler(GetRetryPolicy())
- .AddPolicyHandler(GetCircuiBreakerPolicy());
- return services;
- }
- /// <summary>
- /// 重试策略
- /// </summary>
- public static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
- {
- return HttpPolicyExtensions
- .HandleTransientHttpError()
- .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
- .WaitAndRetryAsync(, retryAttempt => TimeSpan.FromSeconds(Math.Pow(, retryAttempt)));
- }
- /// <summary>
- /// 熔断策略
- /// </summary>
- private static IAsyncPolicy<HttpResponseMessage> GetCircuiBreakerPolicy()
- {
- return HttpPolicyExtensions
- .HandleTransientHttpError()
- .CircuitBreakerAsync(, TimeSpan.FromSeconds());
- }
- }
这里我们通过Polly分别配置了重试和熔断的策略,当发生404、500、408(超时)问题的时候会重试6次,间隔时间2秒;熔断策略是如果有5个请求发生500或者超时则开启熔断,时间是30秒,Polly可以配置非常详细的策略,以后有时间再专门介绍(其实是我现在不会。。。对不起)。因为这里Polly是结合HttpClientFactory来使用的,所以我们需要使用上面的代码:
- services.AddHttpClient("MI")
- .AddPolicyHandler(GetRetryPolicy())
- .AddPolicyHandler(GetCircuiBreakerPolicy());
这里可以理解为我们创建了一个名称为“MI”的HttpClientFactory,然后为其配置了重试和熔断策略,这里顺带提一句是,HttpClientFactory是在.net core 2.1中加入的,它解决了之前HttpClient的资源释放不及时的痛点,之前使用HttpClient时我们需要使用using或者创建静态变量,前者的问题是频繁的创建和销毁带来的资源损耗,不仅仅和对象资源,因为HttpClient还涉及到网络资源,后者则会导致资源释放不及时,静态资源如果不进行处理会一直存在,而HttpClientFactory内部会缓存连接资源,同时会在不使用后的一段间隔时间后进行销毁,同时内存会维护一个队列,单例。
添加完上面这些后我们还需要在ConfigureServices方法中进行注册:
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddCustomMvc(Configuration).AddHttpServices();
- }
我为API的调用封装了一个接口层:
- public interface IApiHelperService
- {
- Task<T> PostAsync<T>(string url, IRequest request);
- Task<T> GetAsync<T>(string url);
- }
- public class ApiHelperService : IApiHelperService
- {
- private readonly IHttpClientFactory _httpClientFactory;
- private readonly IMemoryCache cache;
- private readonly ILogger<ApiHelperService> _logger;
- public ApiHelperService(IMemoryCache cache, ILogger<ApiHelperService> _logger, IHttpClientFactory _httpClientFactory)
- {
- this._httpClientFactory = _httpClientFactory;
- this.cache = cache;
- this._logger = _logger;
- }
- /// <summary>
- /// HttpClient实现Post请求
- /// </summary>
- public async Task<T> PostAsync<T>(string url, IRequest request)
- {
- var http = _httpClientFactory.CreateClient("MI");
- //添加Token
- var token = await GetToken();
- http.SetBearerToken(token);
- //使用FormUrlEncodedContent做HttpContent
- var httpContent = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
- //await异步等待回应
- var response = await http.PostAsync(url, httpContent);
- //确保HTTP成功状态值
- response.EnsureSuccessStatusCode();
- //await异步读取
- string Result = await response.Content.ReadAsStringAsync();
- var Item = JsonConvert.DeserializeObject<T>(Result);
- return Item;
- }
- }
图中标红的部分就是使用带有Polly策略的IHttpClientFactory来创建HttpClient,然后进行Post调用,Get调用也是同样的。
然后我们启动Web项目,开启控制台模式进行日志查看,访问登录功能:
我们可以看到,一共访问了登录方法两次,第一次发生了404错误,接着自动又请求了一次,成功。
这里只是做一次演示,接下来会在Ocelot网关中接入Polly,这样可以避免在每个项目里都进行这样的配置,当然如果项目里有功能需要进行特许的策略配置,是可以采用这种方式的。
.Net Core 商城微服务项目系列(五):使用Polly处理服务错误的更多相关文章
- .Net Core 商城微服务项目系列(一):使用IdentityServer4构建基础登录验证
这里第一次搭建,所以IdentityServer端比较简单,后期再进行完善. 1.新建API项目MI.Service.Identity,NuGet引用IdentityServer4,添加类InMemo ...
- .Net Core 商城微服务项目系列(六):搭建自己的Nuget包服务器
当我们使用微服务架构之后,紧接而来的问题便是服务之间的程序集引用问题,可能没接触过的同学不太理解这句话,都已经微服务化了为什么还要互相引用程序集,当然可以不引用.但是我们会有这样一种情况,我们的每个接 ...
- .Net Core 商城微服务项目系列(十):使用SkyWalking构建调用链监控(2019-02-13 13:25)
SkyWalking的安装和简单使用已经在前面一篇介绍过了,本篇我们将在商城中添加SkyWalking构建调用链监控. 顺带一下怎么把ES设置为Windows服务,cd到ES的bin文件夹,运行ela ...
- .Net Core 商城微服务项目系列(二):使用Ocelot + Consul构建具备服务注册和发现功能的网关
1.服务注册 在上一篇的鉴权和登录服务中分别通过NuGet引用Consul这个包,同时新增AppBuilderExtensions类: public static class AppBuilderEx ...
- .Net Core 商城微服务项目系列(十一):MQ消费端独立为Window服务+消息处理服务
之前使用MQ的时候是通过封装成dll发布Nuget包来使用,消息的发布和消费都耦合在使用的站点和服务里,这样会造成两个问题: 1.增加服务和站点的压力,因为每次消息的消费就意味着接口的调用,这部分的压 ...
- 微服务项目开发学成在线_day01_CMS服务端开发
05-CMS需求分析-什么是CMS 什么是CMS?CMS (Content Management System)即内容管理系统,不同的项目对CMS的定位不同.CMS有哪些类型? 每个公司对每个项目的C ...
- Windows服务项目打包成安装包(Windows服务)-----------VS2017项目程序打包成.msi或者.exe
VS2017项目程序打包成.msi或者.exe Windows服务项目使用VS2017项目程序打包成.msi或者.exe安装包 项目打包成安装包(Windows服务) 1.安装打包插件:Microso ...
- .Net Core 商城微服务项目系列(十五): 构建定时任务调度和消息队列管理系统
一.系统描述 嗨,好久不见各位老哥,最近有点懒,技术博客写的太少了,因为最近在写小说,写的顺利的话说不定就转行了,哈哈哈哈哈哈哈哈哈. 今天要介绍的是基于.Net Core的定时任务调度和消息队列管理 ...
- .Net Core 商城微服务项目系列(十四):分布式部署携程Apollo构建配置中心
一.开场白 在系统设计里我们有很多配置希望独立于系统之外,而又能够被系统实时读取.但是在传统的系统设计里,配置信息通常是耦合在系统内的,比如.net里通常会放在App.config或者web.conf ...
随机推荐
- POJ-1062 昂贵的聘礼( 最短路 )
题目链接:http://poj.org/problem?id=1062 Description 年轻的探险家来到了一个印 第安部落里.在那里他和酋长的女儿相爱了,于是便向酋长去求亲.酋长要他用1000 ...
- http gzip压缩功能记录
版权声明:本文为博主原创文章,转载请附上原文出处链接. 本文链接:https://www.cnblogs.com/shaoshuai95928/articles/Tomcat.html 最近在spri ...
- uwsgi基本介绍安装和测试--使用Django建立你的第一个网站
一 基本介绍 对像我这样不是专业做网络的人来说,uuwsgi是一个陌生的东西.它是谁?它可以做什么?谁会用到它?其实,在不知道一个东西是什么的情况下,能够快速的了解并使用它,是一门很有艺术性的事情.最 ...
- js生成玫瑰图
html: <canvas id="c" height="600" width="600"></canvas> js ...
- webpack多页应用架构系列(一):一步一步解决架构痛点
这系列文章讲什么? 前些时间,写过一个项目,前后端分离,没有借助任何框架,项目页面特别的多,页面都是html直接写的,许多公共html,写了好多处,有一个地方需要改就得改好多地方,js也是随意写,每个 ...
- 【Offer】[36] 【二叉搜索树与双向链表】
题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的节点,只能调整树中节点指针的指向.比如,输入下图中左边的 ...
- web scraper 抓取数据并做简单数据分析
其实 web scraper 说到底就是那点儿东西,所有的网站都是大同小异,但是都还不同.这也是好多同学总是遇到问题的原因.因为没有统一的模板可用,需要理解了 web scraper 的原理并且对目标 ...
- mysql 复制表结构和表数据
CREATE TABLE a1 ( id INT NOT NULL AUTO_INCREMENT COMMENT '编号', txt VARCHAR(20) NOT NULL DEFAULT '' C ...
- Newtonsoft.Json 序列化
当我们对一个json数组进行反序列化用Newtonsoft.Json.JsonConvert.DeserializeObject<T>() 通常会报此错误 Newtonsoft.Json. ...
- oracle用imp导入dmp文件
oracle命令行登录 sqlplus 用户名/密码 创建用户 create user 用户 identified by 密码 ; 创建表空间 create tablespace 表空间名 dataf ...